]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: vhci-hcd: Do not drop references before new references are gained
authorOliver Neukum <oneukum@suse.com>
Tue, 9 Jul 2024 11:38:41 +0000 (13:38 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2024 08:39:04 +0000 (10:39 +0200)
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: Oliver Neukum <oneukum@suse.com>
Cc: stable <stable@kernel.org>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20240709113851.14691-1-oneukum@suse.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/usbip/vhci_hcd.c

index 82650c11e4516125777dc55e4719e398fbbb644c..302a89aeb258a54211406ceb89cc89fdcbcf5519 100644 (file)
@@ -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) {
+               struct usb_device *old;
                __u8 type = usb_pipetype(urb->pipe);
                struct usb_ctrlrequest *ctrlreq =
                        (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
                        goto no_need_xmit;
                }
 
+               old = vdev->udev;
                switch (ctrlreq->bRequest) {
                case USB_REQ_SET_ADDRESS:
                        /* set_address may come when a device is reset */
                        dev_info(dev, "SetAddress Request (%d) to port %d\n",
                                 ctrlreq->wValue, vdev->rhport);
 
-                       usb_put_dev(vdev->udev);
                        vdev->udev = usb_get_dev(urb->dev);
+                       usb_put_dev(old);
 
                        spin_lock(&vdev->ud.lock);
                        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
                                usbip_dbg_vhci_hc(
                                        "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
 
-                       usb_put_dev(vdev->udev);
                        vdev->udev = usb_get_dev(urb->dev);
+                       usb_put_dev(old);
                        goto out;
 
                default:
@@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(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 usb_device *old = vdev->udev;
        unsigned long flags;
 
        spin_lock_irqsave(&ud->lock, flags);
@@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud)
        vdev->speed  = 0;
        vdev->devid  = 0;
 
-       usb_put_dev(vdev->udev);
        vdev->udev = NULL;
+       usb_put_dev(old);
 
        if (ud->tcp_socket) {
                sockfd_put(ud->tcp_socket);