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 <[email protected]>
> > Fixes: 552d0e17ea04 ("sunrpc: convert queue_wait from global to 
> > per-cache-detail waitqueue")
> > Cc: [email protected]
> > Signed-off-by: Christian Brauner (Amutable) <[email protected]>
> 
> Acked-by: Chuck Lever <[email protected]>

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.

Reply via email to