From: zhang.guodong@linux.dev
To: Trond Myklebust <trondmy@kernel.org>, Anna Schumaker <anna@kernel.org>
Cc: linux-nfs@vger.kernel.org, ZhangGuoDong <zhangguodong@kylinos.cn>,
Jackie Liu <liuyun01@kylinos.cn>
Subject: [PATCH] NFS: Verify symlink inode before caching target
Date: Fri, 3 Jul 2026 14:54:48 +0800 [thread overview]
Message-ID: <20260703065448.210255-1-zhang.guodong@linux.dev> (raw)
From: ZhangGuoDong <zhangguodong@kylinos.cn>
nfs_symlink() copies the symlink target into a folio before issuing the
SYMLINK RPC. After a successful reply, it caches that folio in the
instantiated inode mapping and assumes that the dentry now names a
symlink.
If the dentry is instantiated with a non-symlink inode, the raw symlink
target folio can be inserted into the wrong mapping. When that inode is
a directory, reclaim or unmount later calls nfs_readdir_clear_array()
through nfs_dir_aops and interprets the symlink target as a readdir
cache array, which can lead to invalid kfree() calls.
A vmcore from a 4.19-based kernel showed the crash when reclaiming a
directory mapping on unmount:
Stack trace:
nfs_readdir_clear_array+0x4d/0x70 [nfs]
page_cache_free_page.isra.35+0x1a/0x90
delete_from_page_cache_batch+0x1cf/0x2c0
truncate_inode_pages_range+0x24d/0x910
[...]
nfs_evict_inode+0x15/0x30 [nfs]
evict+0x115/0x2b0
dispose_list+0x48/0x60
evict_inodes+0x16c/0x1b0
generic_shutdown_super+0x3f/0x120
nfs_kill_super+0x1b/0x40 [nfs]
deactivate_locked_super+0x3f/0x70
cleanup_mnt+0x3b/0x80
The current code still has the same unchecked cache insertion pattern,
so it may be susceptible to the same failure mode.
Verify that the instantiated inode is a symlink before caching the
target folio. If the type is wrong, drop the suspect dentry and skip
the cache insertion while preserving the successful SYMLINK result.
Co-developed-by: Jackie Liu <liuyun01@kylinos.cn>
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
Signed-off-by: ZhangGuoDong <zhangguodong@kylinos.cn>
---
fs/nfs/dir.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 2f5f26f93238..d10f060b0b94 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2669,6 +2669,12 @@ int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
return error;
}
+ if (unlikely(!d_is_symlink(dentry))) {
+ d_drop(dentry);
+ folio_put(folio);
+ return 0;
+ }
+
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
/*
--
2.43.0
reply other threads:[~2026-07-03 6:55 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703065448.210255-1-zhang.guodong@linux.dev \
--to=zhang.guodong@linux.dev \
--cc=anna@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=liuyun01@kylinos.cn \
--cc=trondmy@kernel.org \
--cc=zhangguodong@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox