When libusb_submit_transfer() fails in usb_host_handle_control() 
orusb_host_handle_data(), the USBHostRequest already queued via
usb_host_req_alloc() is never freed and its r->p pointer is never
cleared.  The caller (xHCI) may then complete and free the
XHCITransfer that embeds the USBPacket r->p points to, leaving a
dangling pointer in s->requests.  A subsequent
usb_host_abort_xfers() -> usb_host_req_abort() dereferences
r->p->state on already-freed memory.


Call usb_host_req_free(r) before returning, matching the existing
pattern in the #else branch of the BULK_STREAMS case.


Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3595
Fixes: 2b2325ff6491 ("use libusb for usb-host")
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 | 14 ++++++++++++++
&nbsp;1 file changed, 14 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
@@ -1523,6 +1523,13 @@ static void usb_host_handle_control(USBDevice *udev, 
USBPacket *p,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CONTROL_TIMEOUT);
&nbsp; &nbsp; &nbsp;rc = libusb_submit_transfer(r-&gt;xfer);
&nbsp; &nbsp; &nbsp;if (rc != 0) {
+ &nbsp; &nbsp; &nbsp; &nbsp;/*
+ &nbsp; &nbsp; &nbsp; &nbsp; * Free the request to avoid a dangling r-&gt;p 
pointer.
+ &nbsp; &nbsp; &nbsp; &nbsp; * When libusb_submit_transfer fails the caller 
(xHCI) may
+ &nbsp; &nbsp; &nbsp; &nbsp; * free the XHCITransfer that holds the USBPacket 
r-&gt;p points
+ &nbsp; &nbsp; &nbsp; &nbsp; * to, so we must remove r from s-&gt;requests 
before returning.
+ &nbsp; &nbsp; &nbsp; &nbsp; */
+ &nbsp; &nbsp; &nbsp; &nbsp;usb_host_req_free(r);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p-&gt;status = USB_RET_NODEV;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;trace_usb_host_req_complete(s-&gt;bus_num, 
s-&gt;addr, p,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p-&gt;status, 
p-&gt;actual_length);
@@ -1617,6 +1624,13 @@ static void usb_host_handle_data(USBDevice *udev, 
USBPacket *p,


&nbsp; &nbsp; &nbsp;rc = libusb_submit_transfer(r-&gt;xfer);
&nbsp; &nbsp; &nbsp;if (rc != 0) {
+ &nbsp; &nbsp; &nbsp; &nbsp;/*
+ &nbsp; &nbsp; &nbsp; &nbsp; * Free the request to avoid a dangling r-&gt;p 
pointer.
+ &nbsp; &nbsp; &nbsp; &nbsp; * When libusb_submit_transfer fails the caller 
(xHCI) may
+ &nbsp; &nbsp; &nbsp; &nbsp; * free the XHCITransfer that holds the USBPacket 
r-&gt;p points
+ &nbsp; &nbsp; &nbsp; &nbsp; * to, so we must remove r from s-&gt;requests 
before returning.
+ &nbsp; &nbsp; &nbsp; &nbsp; */
+ &nbsp; &nbsp; &nbsp; &nbsp;usb_host_req_free(r);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p-&gt;status = USB_RET_NODEV;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;trace_usb_host_req_complete(s-&gt;bus_num, 
s-&gt;addr, p,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p-&gt;status, 
p-&gt;actual_length);
--
2.34.1






发自我的企业微信

Reply via email to