Re: [PATCH] usbip: fix use-after-free in event_handler()

Aleksandr Nogikh <[email protected]>
Newsgroups org.kernel.vger.linux-usb,dev.linux.lists.syzbot,org.kernel.vger.linux-kernel
Message-ID <CANp29Y51K1Y0Z77oUEQmDpVPjJuz3fQhvvZp2=fw3GWSPiCg3w@mail.gmail.com>
Hi Shuah,

Thanks for reviewing the patch!

On Tue, Aug 4, 2026 at 7:31 PM Shuah Khan <[email protected]> wrote:
>
> On 8/3/26 09:05, syzbot wrote:
> > From: Aleksandr Nogikh <[email protected]>
> >
> > The event_handler function in drivers/usb/usbip/usbip_event.c is a
> > workqueue item responsible for processing events for a struct usbip_device.
> > During device teardown, usbip_stop_eh() is called to wait for the event
> > handler to finish processing. However, usbip_stop_eh() uses
> > wait_event_interruptible() and ignores its return value. If the process
> > unbinding the driver receives a signal, wait_event_interruptible() returns
> > immediately, causing the teardown process to falsely assume the event
> > handler has finished.
>
> Does this mean unbinding didn't happen?

The unbinding did happen (and finished freeing the memory), but
without actually waiting for event_handler() in
drivers/usb/usbip/usbip_event.c to finish processing the removal
event. As the device memory was prematurely freed, we got the
use-after-free crash in event_handler().

For reference, here's a C reproducer for the original bug:
https://syzkaller.appspot.com/text?tag=ReproC&x=16ffb7b9580000
It sets up a timer to deliver a signal and wakes up the
wait_event_interruptible() call.

>
> The teardown process then proceeds to free the
> > usbip_device memory. Meanwhile, the event_handler workqueue is still
> > running and attempts to access the freed usbip_device, resulting in a KASAN
> > slab-use-after-free crash.
> >
> > BUG: KASAN: slab-use-after-free in __mutex_lock_common
> > kernel/locking/rtmutex_api.c:559 [inline]
> > BUG: KASAN: slab-use-after-free in mutex_lock_nested+0x5a/0x1d0
> > kernel/locking/rtmutex_api.c:578
> > Read of size 1 at addr ffff8881145245b0 by task kworker/u8:5/6177
> >
> > Call Trace:
> >   <TASK>
> >   lock_acquire+0x84/0x350 kernel/locking/lockdep.c:5842
> >   __mutex_lock_common kernel/locking/rtmutex_api.c:559 [inline]
> >   mutex_lock_nested+0x5a/0x1d0 kernel/locking/rtmutex_api.c:578
> >   event_handler+0x1e3/0x4a0 drivers/usb/usbip/usbip_event.c:73
> >   process_one_work kernel/workqueue.c:3322 [inline]
> >   process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
> >   worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
> >   kthread+0x388/0x470 kernel/kthread.c:436
> >   ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
> >   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >   </TASK>
> >
> > To fix this, change wait_event_interruptible() to wait_event() in
> > usbip_stop_eh(). This ensures that the teardown process strictly waits for
> > the event handler to finish its execution and drop all references to the
> > usbip_device before the memory is freed, preventing the use-after-free.
> > This change is safe from deadlocks because usbip_stop_eh() is never called
> > with locks held that the event_handler would need to acquire.
>
> Correct - usbip_stop_eh() is called without lock hold after updating
> the shutdown_busid status to true. However I am curious what happens
> to the unbinding? Should usbip_stop_eh() check the return value of
> wait_event_interruptible() and handle the error instead?

During unbinding, we must wait for the scheduled removal event to
finish before we can safely free the device structures. From what I
see in the code, once we have reached wait_event_interruptible(),
there's no way to abort the process or somehow gracefully handle the
error.

-- 
Aleksandr

>
> thanks,
> -- Shuah
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.