All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Sang-Hoon Choi <csh0052@gmail.com>
Cc: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>,
	Jiri Slaby <jirislaby@kernel.org>,
	linux-remoteproc@vger.kernel.org, linux-serial@vger.kernel.org,
	linux-kernel@vger.kernel.org, Changyul Lee <lcy8047@gmail.com>
Subject: Re: [PATCH] tty: rpmsg: close port lookup-to-get race
Date: Wed, 23 Sep 2026 11:42:17 +0200	[thread overview]
Message-ID: <2026092327-stew-margin-1e89@gregkh> (raw)
In-Reply-To: <20260923001647.1337001-1-csh0052@gmail.com>

On Wed, Sep 23, 2026 at 12:17:41AM +0900, Sang-Hoon Choi wrote:
> rpmsg_tty_install() obtains cport from tty_idr before taking a port
> reference. rpmsg_tty_destruct_port() removes the entry under idr_lock
> and frees cport. If channel removal drops the last reference between
> idr_find() and tty_port_get(), the install path dereferences freed
> memory.
> 
> The first-open path and channel removal can run concurrently.

How?  What causes channel removel?

> tty_mutex
> serializes TTY initialization, but rpmsg_tty_remove() does not take that
> mutex. tty_unregister_device() prevents later opens through cdev_del(),
> but cdev_del() does not wait for an open which has already entered the
> driver. Before rpmsg_tty_install() finishes, the port is not attached to
> the new TTY, so tty_port_tty_hangup() does not close this interval.
> 
> RPMsg channel removal may be initiated asynchronously by the remote
> processor or transport. In the test, the local process only needs
> permission to open the TTY node; channel removal is initiated
> independently.
> 
> I reproduced this with a UML kernel built with KASAN and a synthetic
> RPMsg device using the real rpmsg_tty probe and remove paths. Test-only
> synchronization forces removal after idr_find() and before
> tty_port_get(). The opening process drops to UID 1000 and GID 1000 first.
> The unpatched kernel reports:
> 
>   BUG: KASAN: slab-use-after-free in rpmsg_tty_install
>   Read of size 4 ... by task init/23
>   CPU: 0 UID: 1000 PID: 23
> 
> The allocation stack ends in rpmsg_tty_probe(). The free stack is
> rpmsg_tty_remove() -> tty_port_put() -> rpmsg_tty_destruct_port(), and
> the invalid read is in rpmsg_tty_install().
> 
> Take idr_lock across idr_find() and tty_port_get(). If the entry is gone
> or its reference count has reached zero, fail the installation with
> -ENODEV. With the same forced overlap, the UID 1000 open returns ENODEV
> and KASAN stays quiet.
> 
> The test uses a synthetic transport and deliberately widens the race
> window. It demonstrates the lifetime bug and an unprivileged opener, but
> does not show that an unprivileged user can deliberately cause channel
> removal on every RPMsg platform. I am therefore reporting this as a
> normal lifetime bug.
> 
> Fixes: 7c0408d80579 ("tty: add rpmsg driver")
> Reported-by: Changyul Lee <lcy8047@gmail.com>
> Link: https://lore.kernel.org/all/179000811428.1227592.8003229121862460039.idr-bug-84@gmail.com/
> Assisted-by: LLM
> Signed-off-by: Sang-Hoon Choi <csh0052@gmail.com>
> ---
> Greg, thanks for the feedback. I went back and reproduced the race under
> KASAN before preparing this patch. I can also provide the test-only
> instrumentation and the complete KASAN log if useful.
> 
>  drivers/tty/rpmsg_tty.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c
> index c5fd6d9b3..b2765bae2 100644
> --- a/drivers/tty/rpmsg_tty.c
> +++ b/drivers/tty/rpmsg_tty.c
> @@ -49,12 +49,19 @@ static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *p
>  
>  static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty)
>  {
> -	struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index);
> -	struct tty_port *port;
> +	struct rpmsg_tty_port *cport;
> +	struct tty_port *port = NULL;
>  
> -	tty->driver_data = cport;
> +	mutex_lock(&idr_lock);

guard()?

And if this is a "real" issue, that can affect things, why not use the
built-in locking that idr has to resolve this issue in a much faster way
than this mutex?

thanks,

greg k-h

      parent reply	other threads:[~2026-09-23  9:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-21 16:28 [RFC] tty: rpmsg: possible lookup-to-reference lifetime race Sang-Hoon Choi
2026-09-21 18:50 ` Greg Kroah-Hartman
2026-09-22 15:17   ` [PATCH] tty: rpmsg: close port lookup-to-get race Sang-Hoon Choi
2026-09-22 15:27     ` sashiko-bot
2026-09-23  9:42     ` Greg Kroah-Hartman [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2026092327-stew-margin-1e89@gregkh \
    --to=gregkh@linuxfoundation.org \
    --cc=arnaud.pouliquen@foss.st.com \
    --cc=csh0052@gmail.com \
    --cc=jirislaby@kernel.org \
    --cc=lcy8047@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-remoteproc@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.