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 <hubcap@omnibond.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>pull/1136/head
parent
9640fe5b5e
commit
90341f22c3
|
|
@ -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;
|
||||
|
|
@ -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",
|
||||
|
|
@ -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",
|
||||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue