Commit afdcfd3d authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

usb: vhci-hcd: Do not drop references before new references are gained

At a few places the driver carries stale pointers
to references that can still be used. Make sure that does not happen.
This strictly speaking closes ZDI-CAN-22273, though there may be
similar races in the driver.
Signed-off-by: default avatarOliver Neukum <oneukum@suse.com>
Cc: stable <stable@kernel.org>
Acked-by: default avatarShuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20240709113851.14691-1-oneukum@suse.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 76a7bfc4
...@@ -745,6 +745,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag ...@@ -745,6 +745,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
* *
*/ */
if (usb_pipedevice(urb->pipe) == 0) { if (usb_pipedevice(urb->pipe) == 0) {
struct usb_device *old;
__u8 type = usb_pipetype(urb->pipe); __u8 type = usb_pipetype(urb->pipe);
struct usb_ctrlrequest *ctrlreq = struct usb_ctrlrequest *ctrlreq =
(struct usb_ctrlrequest *) urb->setup_packet; (struct usb_ctrlrequest *) urb->setup_packet;
...@@ -755,14 +756,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag ...@@ -755,14 +756,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
goto no_need_xmit; goto no_need_xmit;
} }
old = vdev->udev;
switch (ctrlreq->bRequest) { switch (ctrlreq->bRequest) {
case USB_REQ_SET_ADDRESS: case USB_REQ_SET_ADDRESS:
/* set_address may come when a device is reset */ /* set_address may come when a device is reset */
dev_info(dev, "SetAddress Request (%d) to port %d\n", dev_info(dev, "SetAddress Request (%d) to port %d\n",
ctrlreq->wValue, vdev->rhport); ctrlreq->wValue, vdev->rhport);
usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev); vdev->udev = usb_get_dev(urb->dev);
usb_put_dev(old);
spin_lock(&vdev->ud.lock); spin_lock(&vdev->ud.lock);
vdev->ud.status = VDEV_ST_USED; vdev->ud.status = VDEV_ST_USED;
...@@ -781,8 +783,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag ...@@ -781,8 +783,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
usbip_dbg_vhci_hc( usbip_dbg_vhci_hc(
"Not yet?:Get_Descriptor to device 0 (get max pipe size)\n"); "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev); vdev->udev = usb_get_dev(urb->dev);
usb_put_dev(old);
goto out; goto out;
default: default:
...@@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud) ...@@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
static void vhci_device_reset(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud)
{ {
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
struct usb_device *old = vdev->udev;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ud->lock, flags); spin_lock_irqsave(&ud->lock, flags);
...@@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud) ...@@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud)
vdev->speed = 0; vdev->speed = 0;
vdev->devid = 0; vdev->devid = 0;
usb_put_dev(vdev->udev);
vdev->udev = NULL; vdev->udev = NULL;
usb_put_dev(old);
if (ud->tcp_socket) { if (ud->tcp_socket) {
sockfd_put(ud->tcp_socket); sockfd_put(ud->tcp_socket);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment