9p: don't WARN_ONCE on racy symlink fid lookup failure

v9fs_init_request() WARN_ONCE()s when v9fs_fid_lookup() fails for a
symlink read via the page cache. This is a benign TOCTOU race: a
concurrent unlink()/rename() can remove the target between the walk
finding the dentry and p9_client_walk() completing, so the lookup
legitimately fails with -ENOENT (observed: dentry=/file0, err=-2).

With panic_on_warn=1, this WARN escalates to a full kernel panic --
an unprivileged local DoS reachable by racing mount() against a
concurrent unlink/rename.

Return the error directly instead of WARN_ONCE().

Reported-by: syzbot+344c09c64fcd8d3d2782@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=344c09c64fcd8d3d2782
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Message-ID: <20260725014448.18711-1-kartikey406@gmail.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
This commit is contained in:
Deepanshu Kartikey 2026-07-25 07:14:48 +05:30 committed by Dominique Martinet
parent 2acd800de8
commit 64f350a594

View File

@ -166,13 +166,16 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
goto no_fid;
p9_fid_get(fid);
} else if (S_ISLNK(rreq->inode->i_mode)) {
/* racing unlink/rename can make this fail with -ENOENT;
* that's expected, not a kernel bug, so don't WARN
*/
dentry = d_find_any_alias(rreq->inode);
if (!dentry)
goto no_fid;
fid = v9fs_fid_lookup(dentry);
dput(dentry);
if (IS_ERR(fid))
goto no_fid;
return PTR_ERR(fid);
} else {
fid = v9fs_fid_find_inode(rreq->inode, writing, INVALID_UID, true);
if (!fid)