Re: [PATCH] fs/namei: fix UAF in pick_link() by unlazying before atime check

From: Al Viro

Date: Mon Jun 01 2026 - 20:46:13 EST


On Tue, Jun 02, 2026 at 05:56:07AM +0530, Deepanshu Kartikey wrote:
> In pick_link(), atime_needs_update() is called while the path walk
> may still be in RCU mode (LOOKUP_RCU set), meaning no reference is
> held on the inode. A concurrent iput() from another task can free
> the inode while atime_needs_update() reads inode->i_opflags (offset
> +2) inside current_time() -> is_mgtime(), causing a use-after-free.
>
> KASAN reports:
> BUG: KASAN: slab-use-after-free in is_mgtime include/linux/fs.h:2313
> Read of size 2 at addr ffff8880407e4282 (offset +2 = i_opflags)
>
> The race:
> Task A (pick_link) Task B (unlinkat)
> ------------------ -----------------
> atime_needs_update(inode) iput(inode)
> current_time(inode) evict()
> is_mgtime(inode) destroy_inode()
> inode->i_opflags UAF inode FREED
>
> Fix: call try_to_unlazy() before atime_needs_update() so that
> a proper inode reference is held before any inode fields are read.
> If try_to_unlazy() detects the inode is already gone, it returns
> false and we exit safely with -ECHILD without touching freed memory.

NAK. This is *not* fixing the real problem; it's papering over the
real breakage. At a guess - in bpffs, if that's the same thing as
in https://lore.kernel.org/all/20260423043906.GN3518998@ZenIV/

Prompt freeing of inode is allowed *ONLY* if inode is never exposed
to lazy pathwalk. It's OK for pipes, but this is not a pipe.