Commit 4e32c25b authored by Christian Brauner's avatar Christian Brauner Committed by Linus Torvalds

libfs: fix get_stashed_dentry()

get_stashed_dentry() tries to optimistically retrieve a stashed dentry
from a provided location.  It needs to ensure to hold rcu lock before it
dereference the stashed location to prevent UAF issues.  Use
rcu_dereference() instead of READ_ONCE() it's effectively equivalent
with some lockdep bells and whistles and it communicates clearly that
this expects rcu protection.

Link: https://lore.kernel.org/r/20240906-vfs-hotfix-5959800ffa68@brauner
Fixes: 07fd7c32 ("libfs: add path_from_stashed()")
Reported-by: syzbot+f82b36bffae7ef78b6a7@syzkaller.appspotmail.com
Fixes: syzbot+f82b36bffae7ef78b6a7@syzkaller.appspotmail.com
Reported-by: syzbot+cbe4b96e1194b0e34db6@syzkaller.appspotmail.com
Fixes: syzbot+cbe4b96e1194b0e34db6@syzkaller.appspotmail.com
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b831f83e
...@@ -2117,12 +2117,12 @@ struct timespec64 simple_inode_init_ts(struct inode *inode) ...@@ -2117,12 +2117,12 @@ struct timespec64 simple_inode_init_ts(struct inode *inode)
} }
EXPORT_SYMBOL(simple_inode_init_ts); EXPORT_SYMBOL(simple_inode_init_ts);
static inline struct dentry *get_stashed_dentry(struct dentry *stashed) static inline struct dentry *get_stashed_dentry(struct dentry **stashed)
{ {
struct dentry *dentry; struct dentry *dentry;
guard(rcu)(); guard(rcu)();
dentry = READ_ONCE(stashed); dentry = rcu_dereference(*stashed);
if (!dentry) if (!dentry)
return NULL; return NULL;
if (!lockref_get_not_dead(&dentry->d_lockref)) if (!lockref_get_not_dead(&dentry->d_lockref))
...@@ -2219,7 +2219,7 @@ int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, ...@@ -2219,7 +2219,7 @@ int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data,
const struct stashed_operations *sops = mnt->mnt_sb->s_fs_info; const struct stashed_operations *sops = mnt->mnt_sb->s_fs_info;
/* See if dentry can be reused. */ /* See if dentry can be reused. */
path->dentry = get_stashed_dentry(*stashed); path->dentry = get_stashed_dentry(stashed);
if (path->dentry) { if (path->dentry) {
sops->put_data(data); sops->put_data(data);
goto out_path; goto out_path;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment