mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
NFS: Verify symlink inode before caching target
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> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
59075fb8b7
commit
3265f1998a
|
|
@ -2673,6 +2673,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));
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user