mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yaohan Li <shunsheng1218@gmail.com>
To: amit@kernel.org, arnd@arndb.de, gregkh@linuxfoundation.org
Cc: rusty@rustcorp.com.au, virtualization@lists.linux.dev,
	linux-kernel@vger.kernel.org
Subject: [PATCH] virtio_console: guard read-side virtqueue access during unplug
Date: Wed, 04 Nov 2026 17:43:51 +0800	[thread overview]
Message-ID: <179378543196.71890.7555371342727156729@gmail.com> (raw)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2761 bytes --]

The virtio-console write path has an unplug fence, but the read path
can still access port->in_vq after device removal has destroyed its
virtqueues. port_has_data() and fill_readbuf() take inbuf_lock without
checking whether the owning port device has gone away.

Clear portdev while holding inbuf_lock during unplug, and check it
under that lock before reading from or re-adding a buffer to the
input virtqueue. Discard an input buffer instead of requeuing it if
the port was unplugged during a userspace copy.

A KASAN-enabled QEMU virtio-serial test reproduced the stale
virtqueue access when read raced with device unbind. The same
injection-assisted sequence did not report a use-after-free with
this change applied.

Fixes: 31610434bc352 ("Virtio console driver")
Assisted-by: ZCode:GLM-4
Signed-off-by: Yaohan Li <shunsheng1218@gmail.com>
---
 drivers/char/virtio_console.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 019bcae81af5c..e97e0daa34395 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -541,10 +541,16 @@ static bool port_has_data(struct port *port)
 
 	ret = false;
 	spin_lock_irqsave(&port->inbuf_lock, flags);
+
+	/* Port is going away. The vqs are already gone. */
+	if (!port->portdev)
+		goto out_unlock;
+
 	port->inbuf = get_inbuf(port);
 	if (port->inbuf)
 		ret = true;
 
+out_unlock:
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
 	return ret;
 }
@@ -725,6 +731,16 @@ static ssize_t fill_readbuf(struct port *port, u8 __user *out_buf,
 		spin_lock_irqsave(&port->inbuf_lock, flags);
 		port->inbuf = NULL;
 
+		/*
+		 * The port may have been unplugged while we were copying
+		 * data out of the buffer: the vqs are then already gone.
+		 */
+		if (!port->portdev) {
+			spin_unlock_irqrestore(&port->inbuf_lock, flags);
+			free_buf(buf, true);
+			return out_count;
+		}
+
 		if (add_inbuf(port->in_vq, buf) < 0)
 			dev_warn(port->dev, "failed add_buf\n");
 
@@ -1568,6 +1584,18 @@ static void unplug_port(struct port *port)
 	 * a close on an open port later from sending a stale control
 	 * message.
 	 */
+	/*
+	 * Null out portdev under inbuf_lock as well, so the read path
+	 * (port_has_data(), fill_readbuf()) cannot race with the vq
+	 * teardown: it checks port->portdev inside the same lock and
+	 * bails out if NULL, preventing any virtqueue access to an
+	 * already torn-down virtqueue — mirroring the outvq_lock fence
+	 * below for the write path.
+	 */
+	spin_lock_irq(&port->inbuf_lock);
+	port->portdev = NULL;
+	spin_unlock_irq(&port->inbuf_lock);
+
 	spin_lock_irq(&port->outvq_lock);
 	port->portdev = NULL;
 	spin_unlock_irq(&port->outvq_lock);
-- 
2.34.1


                 reply	other threads:[~2026-11-04  9:44 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=179378543196.71890.7555371342727156729@gmail.com \
    --to=shunsheng1218@gmail.com \
    --cc=amit@kernel.org \
    --cc=arnd@arndb.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rusty@rustcorp.com.au \
    --cc=virtualization@lists.linux.dev \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®