Skip to content

Commit 90341f2

Browse files
author
Al Viro
committed
orangefs_d_revalidate(): use stable parent inode and name passed by caller
->d_name use is a UAF if the userland side of things can be slowed down by attacker. Tested-by: Mike Marshall <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 9640fe5 commit 90341f2

File tree

1 file changed

+8
-11
lines changed

1 file changed

+8
-11
lines changed

fs/orangefs/dcache.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
#include "orangefs-kernel.h"
1414

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

2827
new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP);
29-
if (!new_op) {
30-
ret = -ENOMEM;
31-
goto out_put_parent;
32-
}
28+
if (!new_op)
29+
return -ENOMEM;
3330

3431
new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
3532
new_op->upcall.req.lookup.parent_refn = parent->refn;
36-
strscpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name);
33+
/* op_alloc() leaves ->upcall zeroed */
34+
memcpy(new_op->upcall.req.lookup.d_name, name->name,
35+
min(name->len, ORANGEFS_NAME_MAX - 1));
3736

3837
gossip_debug(GOSSIP_DCACHE_DEBUG,
3938
"%s:%s:%d interrupt flag [%d]\n",
@@ -78,8 +77,6 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)
7877
ret = 1;
7978
out_release_op:
8079
op_release(new_op);
81-
out_put_parent:
82-
dput(parent_dentry);
8380
return ret;
8481
out_drop:
8582
gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d revalidate failed\n",
@@ -115,7 +112,7 @@ static int orangefs_d_revalidate(struct inode *dir, const struct qstr *name,
115112
* If this passes, the positive dentry still exists or the negative
116113
* dentry still does not exist.
117114
*/
118-
if (!orangefs_revalidate_lookup(dentry))
115+
if (!orangefs_revalidate_lookup(dir, name, dentry))
119116
return 0;
120117

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

0 commit comments

Comments
 (0)