Message ID | 20250116052317.485356-14-viro@zeniv.linux.org.uk |
---|---|
State | New |
Headers | show |
Series | [v2,01/20] make sure that DNAME_INLINE_LEN is a multiple of word size | expand |
On Thu, 2025-01-16 at 05:23 +0000, Al Viro wrote: > No need to mess with dget_parent() for the former; for the latter we really should > not rely upon ->d_name.name remaining stable - it's a real-life UAF. > > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > --- > fs/fuse/dir.c | 11 +++-------- > 1 file changed, 3 insertions(+), 8 deletions(-) > > diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c > index d9e9f26917eb..7e93a8470c36 100644 > --- a/fs/fuse/dir.c > +++ b/fs/fuse/dir.c > @@ -196,7 +196,6 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, > struct dentry *entry, unsigned int flags) > { > struct inode *inode; > - struct dentry *parent; > struct fuse_mount *fm; > struct fuse_inode *fi; > int ret; > @@ -228,11 +227,9 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, > > attr_version = fuse_get_attr_version(fm->fc); > > - parent = dget_parent(entry); > - fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), > - &entry->d_name, &outarg); > + fuse_lookup_init(fm->fc, &args, get_node_id(dir), > + name, &outarg); > ret = fuse_simple_request(fm, &args); > - dput(parent); > /* Zero nodeid is same as -ENOENT */ > if (!ret && !outarg.nodeid) > ret = -ENOENT; > @@ -266,9 +263,7 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, > if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) > return -ECHILD; > } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { > - parent = dget_parent(entry); > - fuse_advise_use_readdirplus(d_inode(parent)); > - dput(parent); > + fuse_advise_use_readdirplus(dir); > } > } > ret = 1; Reviewed-by: Jeff Layton <jlayton@kernel.org>
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d9e9f26917eb..7e93a8470c36 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -196,7 +196,6 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, struct dentry *entry, unsigned int flags) { struct inode *inode; - struct dentry *parent; struct fuse_mount *fm; struct fuse_inode *fi; int ret; @@ -228,11 +227,9 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, attr_version = fuse_get_attr_version(fm->fc); - parent = dget_parent(entry); - fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), - &entry->d_name, &outarg); + fuse_lookup_init(fm->fc, &args, get_node_id(dir), + name, &outarg); ret = fuse_simple_request(fm, &args); - dput(parent); /* Zero nodeid is same as -ENOENT */ if (!ret && !outarg.nodeid) ret = -ENOENT; @@ -266,9 +263,7 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name, if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) return -ECHILD; } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { - parent = dget_parent(entry); - fuse_advise_use_readdirplus(d_inode(parent)); - dput(parent); + fuse_advise_use_readdirplus(dir); } } ret = 1;
No need to mess with dget_parent() for the former; for the latter we really should not rely upon ->d_name.name remaining stable - it's a real-life UAF. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/fuse/dir.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)