* [PATCH] NFS: Verify symlink inode before caching target
@ 2026-07-03 6:54 zhang.guodong
0 siblings, 0 replies; only message in thread
From: zhang.guodong @ 2026-07-03 6:54 UTC (permalink / raw)
To: Trond Myklebust, Anna Schumaker; +Cc: linux-nfs, ZhangGuoDong, Jackie Liu
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
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-03 6:55 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03 6:54 [PATCH] NFS: Verify symlink inode before caching target zhang.guodong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox