Re: [PATCH] net/9p/usbg: Fix use-after-free in disable_usb9pfs()
From: Yizhou Zhao
Date: Sat Jun 13 2026 - 08:48:56 EST
Hi Xiao,
Thanks for the PoC. I re-tested it on a fresh upstream tree
(2d3090a8aeb5, 7.1.0-rc7-00016-g2d3090a8aeb5) with KASAN and lockdep
enabled, and I can reproduce the reported call trace:
strcmp
look_up_lock_class
register_lock_class
__lock_acquire
lock_acquire
__wake_up
p9_client_cb
usb9pfs_clear_tx
Without lockdep, the same PoC reaches the same usb9pfs_clear_tx() ->
p9_client_cb() -> __wake_up() path, but it shows up as an RCU stall
instead of the lockdep/strcmp crash.
On Sat, Jun 13, 2026 at 04:27:38AM +0800, XIAO WU wrote:
> I wrote the following PoC to trigger this bug. It creates a USB
> gadget with a usb9pfs function, sets buflen=0 so that alloc_ep_req()
> fails in alloc_requests(), which frees in_req without NULLing the
> pointer, then unbinds the gadget to trigger usb9pfs_clear_tx() on the
> dangling in_req.
However, I think the actual trigger is slightly different from the
allocation-failure path described in the mail. Setting buflen to 0 does
not make alloc_ep_req() fail in my test: usb_ep_align(..., 0) produces a
zero length, and kmalloc(0) returns ZERO_SIZE_PTR rather than NULL. So
alloc_requests() still succeeds.
The failure seems to happen because in_req->context is still initialized
as the f_usb9pfs pointer. During disconnect, usb9pfs_clear_tx() treats
that context as a struct p9_req_t * and passes it to p9_client_cb(),
which eventually calls wake_up() on a bogus req->wq. With lockdep
enabled, that bogus waitqueue/lock state leads to the strcmp ->
register_lock_class() crash.
So I agree that the PoC exposes a real usb9pfs teardown/context bug, but
it looks independent from the endpoint-disable/free-ordering UAF fixed by
my patch. I think it would be clearer to handle it in a separate patch,
with a commit message describing the actual trigger path.
Thanks,
Yizhou