* [PATCH v2] virtio_console: defer HVC polling out of the virtqueue callback
@ 2026-11-05 11:44 Yaohan Li
0 siblings, 0 replies; only message in thread
From: Yaohan Li @ 2026-11-05 11:44 UTC (permalink / raw)
To: amit, arnd, gregkh; +Cc: rusty, virtualization, linux-kernel
The input virtqueue callback calls hvc_poll() on port->cons.hvc
without any synchronization against HVC adapter removal. A port
removed via a VIRTIO_CONSOLE_PORT_REMOVE control message runs
unplug_port() -> hvc_remove(), which drops the adapter's last
tty_port reference and frees it, while the callback may still be
about to dereference the freed adapter:
BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave
BUG: KASAN: slab-use-after-free in __hvc_poll
Both sides hold only the port kref; nothing protects
struct hvc_struct between the callback's pointer read and its use.
Do not touch the adapter from hard IRQ context at all. Only wake
the HVC worker with hvc_kick(): khvcd polls registered adapters
while holding hvc_structs_mutex, which also serializes
hvc_port_destruct() before it removes the adapter from the list
and frees it, so the worker can never poll a removed adapter. The
callback now only reads the adapter pointer value (never
dereferences it) to decide whether to kick; a stale value can cause
at most a harmless extra kick. The IS_ERR_OR_NULL() check also
avoids waking the worker for a port whose hvc_alloc() failed.
The price is one extra scheduling latency for console input
delivery. A 64-byte echo benchmark over a virtio console port
shows no significant difference (RTT p50 0.089 ms vs 0.083 ms,
855 vs 767 msg/s).
The race and the fix were verified with an injection-assisted QEMU
setup: stalling the callback between the waitqueue wakeup and the
adapter access while a QMP device_del removes the port produces six
slab-use-after-free reports per run on the unpatched kernel and
zero reports with this change.
This issue was investigated and the fix was developed with AI
assistance (ZCode/GLM-4).
Fixes: 203baab8ba319 ("virtio: console: Introduce function to hand off data from host to readers")
Signed-off-by: Yaohan Li <shunsheng1218@gmail.com>
---
Changes since v1:
- v1 protected the in-flight hvc_poll() call with an RCU read-side
critical section and published a NULL adapter before removal. This
version drops the RCU scheme entirely: the virtqueue callback no
longer touches the HVC adapter at all and only wakes the HVC worker,
which polls adapters under hvc_structs_mutex - the same mutex that
serializes adapter destruction - so it can never poll a removed
adapter, and the unplug side needs no change.
- Verified with an injection-assisted A/B run at the same stall point
(in_intr+0x18b, between the waitqueue wakeup and the adapter
access): the unpatched kernel reports six slab-use-after-frees per
run, this patch reports none. Round-trip latency and throughput on
a console port are unchanged (p50 0.089 ms vs 0.083 ms).
- resize_console() and the control-message HVC accesses remain out of
scope, as in v1.
v1: https://lore.kernel.org/r/179378553951.72222.12851179500568566393@gmail.com/
drivers/char/virtio_console.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 019bcae81af5c..c5b3a6c0ff3d7 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1820,7 +1820,14 @@ static void in_intr(struct virtqueue *vq)
wake_up_interruptible(&port->waitqueue);
- if (is_console_port(port) && hvc_poll(port->cons.hvc))
+ /*
+ * Leave HVC polling to the khvcd thread: it walks its adapter list
+ * under hvc_structs_mutex, which also serializes adapter
+ * destruction, so it cannot poll a removed adapter. Do not touch
+ * the adapter here: hvc_remove() can free it concurrently during
+ * port unplug and this callback holds no reference to it.
+ */
+ if (!IS_ERR_OR_NULL(READ_ONCE(port->cons.hvc)))
hvc_kick();
kref_put(&port->kref, remove_port);
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.34.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-05 11:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-05 11:44 [PATCH v2] virtio_console: defer HVC polling out of the virtqueue callback Yaohan Li
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®