Re: [PATCH RFC 27/38] sunrpc: make queue_wait a global wait queue again
From: Christian Brauner
Date: Tue Nov 03 2026 - 13:05:32 EST
On Mon, Nov 02, 2026 at 10:12:12AM -0500, Chuck Lever wrote:
>
>
> On Mon, Nov 2, 2026, at 9:21 AM, Christian Brauner wrote:
> > Since commit 552d0e17ea04 ("sunrpc: convert queue_wait from global to
> > per-cache-detail waitqueue") poll() and epoll queue their waiters for a
> > channel file on the queue_wait head in struct cache_detail. But the
> > cache_detail can be freed while its channel file is still open and
> > waited on.
> >
> > The procfs channel files of a network namespace are removed when the
> > namespace goes away. Removing a procfs file waits for the callers that
> > are in one of its methods right now and then calls ->release on every
> > file that is still open (cf. close_pdeo()). The waiters that poll() and
> > epoll left on the head stay queued until their file is really closed.
> > So:
> >
> > sunrpc_exit_net()
> > -> ip_map_cache_destroy()
> > -> cache_unregister_net()
> > -> remove_cache_proc_entries()
> > -> proc_remove() // ->release, the waiters stay queued
> > -> cache_destroy_net() // kfree(cd)
> >
> > and when poll() returns remove_wait_queue() writes to the freed
> > cache_detail:
> >
> > BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x4b/0xa0
> > Read of size 1 at addr ff110001131bb570 by task sunrpc-poll-uaf/242
> > Call Trace:
> > remove_wait_queue+0x22/0x1c0
> > poll_freewait+0xc2/0x230
> > do_sys_poll+0x9ba/0xd50
> > __x64_sys_poll+0x165/0x470
> > Freed by task 12:
> > kfree+0x267/0x620
> > sunrpc_exit_net+0x34/0x80
> > ops_undo_list+0x271/0x8d0
> > cleanup_net+0x3f3/0x860
> >
> > Closing an epoll instance that watches the file gets there through
> > ep_unregister_pollwait() instead.
> >
> > The channel files of a network namespace belong to the root of its
> > user namespace and cache_open() doesn't check for a capability. So an
> > unprivileged user can open the channel file of a namespace of its own
> > from the outside, poll it and let the namespace die.
> >
> > Go back to a single static wait queue that never goes away. A wakeup
> > for one cache wakes the waiters of all caches again but cache_poll()
> > reports per cache_detail so that's just a spurious wakeup. procfs
> > should really own the wait queue of its files like kernfs does but
> > that's nothing for stable.
> >
> > Reported-by: Chris Mason <mason@xxxxxxxxxx>
> > Fixes: 552d0e17ea04 ("sunrpc: convert queue_wait from global to
> > per-cache-detail waitqueue")
> > Cc: stable@xxxxxxxxxxxxxxx
> > Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
>
> Acked-by: Chuck Lever <cel@xxxxxxxxxx>
Fwiw, I have a patch series on top of this that makes procfs own the
waitqueue and then this whole UAF issues goes away structurally and you
get to elide that global thing here.