usb_host_nodev() lazily creates s->bh_nodev andusb_host_post_load() lazily 
creates s->bh_postld, but
usb_host_unrealize() never calls qemu_bh_delete() on either.  If a BH
is still pending when unrealize returns, its callback dereferences the
freed USBHostDevice.


Delete both BHs in usb_host_unrealize() after usb_host_close()
returns.  They must be deleted after close because usb_host_close()
can process libusb callbacks that call usb_host_nodev(), which lazily
recreates bh_nodev.  Deleting it before close could therefore leave a
recreated BH alive after unrealize.


Buglink: https://gitlab.com/qemu-project/qemu/-/work_items/3595
Fixes: 95efb20c7148 ("usb-host: live migration support for libusb")
Reported-by: Haotian Jiang of Tencent Security (Yunding Lab) 
<[email protected]&gt;
Signed-off-by: Haotian Jiang <[email protected]&gt;
Cc: [email protected]
---
&nbsp;hw/usb/host-libusb.c | 15 +++++++++++++++
&nbsp;1 file changed, 15 insertions(+)


diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1271,6 +1271,21 @@ static void usb_host_unrealize(USBDevice *udev)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;QTAILQ_REMOVE(&amp;hostdevs, s, next);
&nbsp; &nbsp; &nbsp;}
&nbsp; &nbsp; &nbsp;usb_host_close(s);
+ &nbsp; &nbsp;/*
+ &nbsp; &nbsp; * Delete bottom halves after usb_host_close(). &nbsp;During 
close,
+ &nbsp; &nbsp; * libusb callbacks (usb_host_req_complete_ctrl/data) can call
+ &nbsp; &nbsp; * usb_host_nodev() which lazily creates bh_nodev. &nbsp;If we
+ &nbsp; &nbsp; * deleted them before close, a newly created BH would leak and
+ &nbsp; &nbsp; * fire after unrealize, dereferencing freed USBHostDevice.
+ &nbsp; &nbsp; */
+ &nbsp; &nbsp;if (s-&gt;bh_nodev) {
+ &nbsp; &nbsp; &nbsp; &nbsp;qemu_bh_delete(s-&gt;bh_nodev);
+ &nbsp; &nbsp; &nbsp; &nbsp;s-&gt;bh_nodev = NULL;
+ &nbsp; &nbsp;}
+ &nbsp; &nbsp;if (s-&gt;bh_postld) {
+ &nbsp; &nbsp; &nbsp; &nbsp;qemu_bh_delete(s-&gt;bh_postld);
+ &nbsp; &nbsp; &nbsp; &nbsp;s-&gt;bh_postld = NULL;
+ &nbsp; &nbsp;}
&nbsp;}


&nbsp;static void usb_host_cancel_packet(USBDevice *udev, USBPacket *p)
--
2.34.1





发自我的企业微信

Reply via email to