Re: Fwd: BUG: KASAN: use-after-free in usb_hcd_unlink_urb+0x5f/0x170 drivers/usb/core/hcd.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 24, 2020 at 10:14:39AM -0400, Alan Stern wrote:
> On Mon, 23 Mar 2020, Kyungtae Kim wrote:
>
> > We report a bug (in linux-5.5.11) found by FuzzUSB (a modified version
> > of syzkaller)
> >
> > In function usb_hcd_unlink_urb (driver/usb/core/hcd.c:1607), it tries to
> > read "urb->use_count". But it seems the instance "urb" was
> > already freed (right after urb->dev at line 1597) by the function "urb_destroy"
> > in a different thread, which caused memory access violation.
> > To solve, it may need to check if urb is valid before urb->use_count,
> > to avoid such freed memory access.
>
> No, the problem is "free while still in use", caused by the fact that
> usb_sg_cancel() fails to indicate it is using the data structures.
>
> > kernel config: https://kt0755.github.io/etc/config_v5.5.11
> >
> > ==================================================================
> > BUG: KASAN: use-after-free in atomic_read
> > include/asm-generic/atomic-instrumented.h:26 [inline]
> > BUG: KASAN: use-after-free in usb_hcd_unlink_urb+0x5f/0x170
> > drivers/usb/core/hcd.c:1607
> > Read of size 4 at addr ffff888065379610 by task kworker/u4:1/27
>
> Here is a patch which ought to fix the problem.  Can you test it?
>
> Alan Stern
>
>
> Index: usb-devel/drivers/usb/core/message.c
> ===================================================================
> --- usb-devel.orig/drivers/usb/core/message.c
> +++ usb-devel/drivers/usb/core/message.c
> @@ -588,12 +588,13 @@ void usb_sg_cancel(struct usb_sg_request
>       int i, retval;
>
>       spin_lock_irqsave(&io->lock, flags);
> -     if (io->status) {
> +     if (io->status || io->count == 0) {
>               spin_unlock_irqrestore(&io->lock, flags);
>               return;
>       }
>       /* shut everything down */
>       io->status = -ECONNRESET;
> +     io->count++;            /* Keep the request alive until we're done */
>       spin_unlock_irqrestore(&io->lock, flags);
>
>       for (i = io->entries - 1; i >= 0; --i) {
> @@ -607,6 +608,12 @@ void usb_sg_cancel(struct usb_sg_request
>                       dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
>                                __func__, retval);
>       }
> +
> +     spin_lock_irqsave(&io->lock, flags);
> +     io->count--;
> +     if (!io->count)
> +             complete(&io->complete);
> +     spin_unlock_irqrestore(&io->lock, flags);
>  }
>  EXPORT_SYMBOL_GPL(usb_sg_cancel);
>
>

Thanks for the patch. Unfortunately, we don't have a repro program to
test right now.

Regards,
Kyungtae Kim



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux