Skip to content

Commit

Permalink
orangefs_d_revalidate(): use stable parent inode and name passed by c…
Browse files Browse the repository at this point in the history
…aller

->d_name use is a UAF if the userland side of things can be slowed down
by attacker.

Tested-by: Mike Marshall <hubcap@omnibond.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Jan 28, 2025
1 parent 9640fe5 commit 90341f2
Showing 1 changed file with 8 additions and 11 deletions.
19 changes: 8 additions & 11 deletions fs/orangefs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
#include "orangefs-kernel.h"

/* Returns 1 if dentry can still be trusted, else 0. */
static int orangefs_revalidate_lookup(struct dentry *dentry)
static int orangefs_revalidate_lookup(struct inode *parent_inode, const struct qstr *name,
struct dentry *dentry)
{
struct dentry *parent_dentry = dget_parent(dentry);
struct inode *parent_inode = parent_dentry->d_inode;
struct orangefs_inode_s *parent = ORANGEFS_I(parent_inode);
struct inode *inode = dentry->d_inode;
struct orangefs_kernel_op_s *new_op;
Expand All @@ -26,14 +25,14 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)
gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__);

new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
if (!new_op) {
ret = -ENOMEM;
goto out_put_parent;
}
if (!new_op)
return -ENOMEM;

new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
new_op->upcall.req.lookup.parent_refn = parent->refn;
strscpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name);
/* op_alloc() leaves ->upcall zeroed */
memcpy(new_op->upcall.req.lookup.d_name, name->name,
min(name->len, ORANGEFS_NAME_MAX - 1));

gossip_debug(GOSSIP_DCACHE_DEBUG,
"%s:%s:%d interrupt flag [%d]\n",
Expand Down Expand Up @@ -78,8 +77,6 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)
ret = 1;
out_release_op:
op_release(new_op);
out_put_parent:
dput(parent_dentry);
return ret;
out_drop:
gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
Expand Down Expand Up @@ -115,7 +112,7 @@ static int orangefs_d_revalidate(struct inode *dir, const struct qstr *name,
* If this passes, the positive dentry still exists or the negative
* dentry still does not exist.
*/
if (!orangefs_revalidate_lookup(dentry))
if (!orangefs_revalidate_lookup(dir, name, dentry))
return 0;

/* We do not need to continue with negative dentries. */
Expand Down

0 comments on commit 90341f2

Please sign in to comment.