From: Shuah Khan <skhan@linuxfoundation.org>
To: Aleksandr Nogikh <nogikh@google.com>
Cc: syzbot <syzbot@kernel.org>,
syzkaller-bugs@googlegroups.com,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org, Shuah Khan <shuah@kernel.org>,
Valentina Manea <valentina.manea.m@gmail.com>,
Nobuo Iwata <nobuo.iwata@fujixerox.co.jp>,
i@zenithal.me, linux-kernel@vger.kernel.org,
syzbot@lists.linux.dev, Shuah Khan <skhan@linuxfoundation.org>
Subject: Re: [PATCH] usbip: fix use-after-free in event_handler()
Date: Mon, 10 Aug 2026 13:33:18 -0600 [thread overview]
Message-ID: <34d4ca1b-ce89-444f-bb02-245287edfad0@linuxfoundation.org> (raw)
In-Reply-To: <CANp29Y51K1Y0Z77oUEQmDpVPjJuz3fQhvvZp2=fw3GWSPiCg3w@mail.gmail.com>
On 8/7/26 08:18, Aleksandr Nogikh wrote:
> Hi Shuah,
>
> Thanks for reviewing the patch!
>
> On Tue, Aug 4, 2026 at 7:31 PM Shuah Khan <skhan@linuxfoundation.org> wrote:
>>
>> On 8/3/26 09:05, syzbot wrote:
>>> From: Aleksandr Nogikh <nogikh@google.com>
>>>
>>> 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.
Thanks.
>
>>
>> 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.
>
Yes I agree with you on rewinding being hard.
Care to explain the scope of this assist?
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
thanks,
-- Shuah
next prev parent reply other threads:[~2026-08-10 19:33 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 15:05 [PATCH] usbip: fix use-after-free in event_handler() syzbot
2026-08-04 17:31 ` Shuah Khan
2026-08-07 14:18 ` Aleksandr Nogikh
2026-08-10 19:33 ` Shuah Khan [this message]
2026-08-11 13:07 ` Aleksandr Nogikh
2026-08-11 22:39 ` Shuah Khan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=34d4ca1b-ce89-444f-bb02-245287edfad0@linuxfoundation.org \
--to=skhan@linuxfoundation.org \
--cc=gregkh@linuxfoundation.org \
--cc=i@zenithal.me \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=nobuo.iwata@fujixerox.co.jp \
--cc=nogikh@google.com \
--cc=shuah@kernel.org \
--cc=syzbot@kernel.org \
--cc=syzbot@lists.linux.dev \
--cc=syzkaller-bugs@googlegroups.com \
--cc=valentina.manea.m@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.