]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
libfs: fix get_stashed_dentry()
authorChristian Brauner <brauner@kernel.org>
Fri, 6 Sep 2024 16:22:22 +0000 (18:22 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 Sep 2024 18:08:58 +0000 (11:08 -0700)
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: 07fd7c329839 ("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: Christian Brauner <brauner@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/libfs.c

index 02602d00939e9688250770ae5195cab2cb5b2663..b64b4c44cfea87ba0888de8f638def4fe4f8befc 100644 (file)
@@ -2117,12 +2117,12 @@ struct timespec64 simple_inode_init_ts(struct inode *inode)
 }
 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;
 
        guard(rcu)();
-       dentry = READ_ONCE(stashed);
+       dentry = rcu_dereference(*stashed);
        if (!dentry)
                return NULL;
        if (!lockref_get_not_dead(&dentry->d_lockref))
@@ -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;
 
        /* See if dentry can be reused. */
-       path->dentry = get_stashed_dentry(*stashed);
+       path->dentry = get_stashed_dentry(stashed);
        if (path->dentry) {
                sops->put_data(data);
                goto out_path;