| From 728836ebca239810f164262b10211ef59182f811 Mon Sep 17 00:00:00 2001 |
| From: Chengfeng Ye <nicoyip.dev@gmail.com> |
| Date: Sun, 23 Aug 2026 00:45:56 +0800 |
| Subject: vsock/virtio: flush works in dependency order |
| |
| From: Chengfeng Ye <nicoyip.dev@gmail.com> |
| |
| commit 728836ebca239810f164262b10211ef59182f811 upstream. |
| |
| virtio_vsock_remove() stops the virtqueues and then flushes each work |
| item before freeing the enclosing virtio_vsock. The current order does |
| not account for dependencies between those items: tx_work may queue |
| send_pkt_work, and send_pkt_work may queue rx_work. |
| |
| In particular, send_pkt_work can set restart_rx and release tx_lock. |
| The remove path can then stop the queues and flush rx_work before |
| send_pkt_work queues it. Although the later send_pkt_work flush waits |
| for that producer to finish, nothing waits for the newly queued rx_work, |
| so kfree(vsock) can race with it. |
| |
| KASAN reported: |
| |
| BUG: KASAN: slab-use-after-free in |
| virtio_transport_rx_work+0x487/0x4b0 |
| Read of size 8 at addr ffff888114c2b008 by task kworker/1:1/47 |
| Workqueue: virtio_vsock virtio_transport_rx_work |
| Call Trace: |
| virtio_transport_rx_work+0x487/0x4b0 |
| process_one_work+0x688/0x1120 |
| worker_thread+0x45b/0xd10 |
| Allocated by task 1: |
| virtio_vsock_probe+0xef/0x6b0 |
| Freed by task 84: |
| kfree+0x131/0x3c0 |
| virtio_vsock_remove+0xd1/0x100 |
| |
| Flush the works in producer-to-consumer order. virtio_vsock_vqs_del() |
| has already disabled the queue callbacks and cleared the run flags, so |
| after tx_work and send_pkt_work are drained, no source remains that can |
| queue rx_work after its flush. |
| |
| Fixes: 0ea9e1d3a9e3 ("VSOCK: Introduce virtio_transport.ko") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com> |
| Link: https://patch.msgid.link/20260822164556.3750959-1-nicoyip.dev@gmail.com |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/vmw_vsock/virtio_transport.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/net/vmw_vsock/virtio_transport.c |
| +++ b/net/vmw_vsock/virtio_transport.c |
| @@ -714,10 +714,10 @@ static void virtio_vsock_remove(struct v |
| /* Other works can be queued before 'config->del_vqs()', so we flush |
| * all works before to free the vsock object to avoid use after free. |
| */ |
| - flush_work(&vsock->rx_work); |
| flush_work(&vsock->tx_work); |
| flush_work(&vsock->event_work); |
| flush_work(&vsock->send_pkt_work); |
| + flush_work(&vsock->rx_work); |
| |
| mutex_unlock(&the_virtio_vsock_mutex); |
| |