[PATCH] virt: vboxguest: fix use-after-free in balloon work

Fan Wu <[email protected]>
Newsgroups dev.linux.lists.virtualization,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
VMMDEV_EVENT_BALLOON_CHANGE_REQUEST is reported only after a guest
userspace client enables it with VBOXGUEST_IOCTL_SET_EVENT_FILTER.
The interrupt handler then queues the balloon work, which reads and
writes the mem_balloon.get_req and change_req request buffers.

vbg_pci_remove() calls free_irq() before vbg_core_exit(), but
free_irq() only waits for the handler to return, not for any work it
has queued.  A balloon work still running on system_wq therefore
touches the request buffers after vbg_core_exit() has freed them:

  CPU 0 (remove)          IRQ handler              system_wq
  free_irq()              schedule_work(...)
                         return
  vbg_core_exit()
    vbg_req_free(...)                             vbg_balloon_work()
                                                   req->event_ack = ...

Fix this by calling cancel_work_sync() on mem_balloon.work in
vbg_core_exit(), before the request buffers are freed.  The worker
does not requeue itself, and the interrupt handler, the only place
that queues it, can no longer run when vbg_core_exit() is reached:
vbg_pci_remove() has already called free_irq(), and on the probe
error path the irq was never requested.  Draining the work once is
therefore sufficient.

This issue was found by an in-house static analysis tool.

Fixes: 0ba002bc4393 ("virt: Add vboxguest driver for Virtual Box Guest integration")
Cc: [email protected]
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <[email protected]>
---
 drivers/virt/vboxguest/vboxguest_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c
index b177a534b6a4..884e69d00f72 100644
--- a/drivers/virt/vboxguest/vboxguest_core.c
+++ b/drivers/virt/vboxguest/vboxguest_core.c
@@ -1048,6 +1048,8 @@ int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events)
  */
 void vbg_core_exit(struct vbg_dev *gdev)
 {
+	cancel_work_sync(&gdev->mem_balloon.work);
+
 	vbg_heartbeat_exit(gdev);
 	vbg_guest_mappings_exit(gdev);
 
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.