Skip to content

Commit 8552909

Browse files
jtlaytonidryomov
authored andcommitted
ceph: make ceph_fill_trace and ceph_get_name decrypt names
When we get a dentry in a trace, decrypt the name so we can properly instantiate the dentry or fill out ceph_get_name() buffer. Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Xiubo Li <xiubli@redhat.com> Reviewed-and-tested-by: Luís Henriques <lhenriques@suse.de> Reviewed-by: Milind Changire <mchangir@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent 457117f commit 8552909

2 files changed

Lines changed: 60 additions & 14 deletions

File tree

fs/ceph/export.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "super.h"
99
#include "mds_client.h"
10+
#include "crypto.h"
1011

1112
/*
1213
* Basic fh
@@ -535,7 +536,9 @@ static int ceph_get_name(struct dentry *parent, char *name,
535536
{
536537
struct ceph_mds_client *mdsc;
537538
struct ceph_mds_request *req;
539+
struct inode *dir = d_inode(parent);
538540
struct inode *inode = d_inode(child);
541+
struct ceph_mds_reply_info_parsed *rinfo;
539542
int err;
540543

541544
if (ceph_snap(inode) != CEPH_NOSNAP)
@@ -547,30 +550,47 @@ static int ceph_get_name(struct dentry *parent, char *name,
547550
if (IS_ERR(req))
548551
return PTR_ERR(req);
549552

550-
inode_lock(d_inode(parent));
551-
553+
inode_lock(dir);
552554
req->r_inode = inode;
553555
ihold(inode);
554556
req->r_ino2 = ceph_vino(d_inode(parent));
555-
req->r_parent = d_inode(parent);
556-
ihold(req->r_parent);
557+
req->r_parent = dir;
558+
ihold(dir);
557559
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
558560
req->r_num_caps = 2;
559561
err = ceph_mdsc_do_request(mdsc, NULL, req);
562+
inode_unlock(dir);
560563

561-
inode_unlock(d_inode(parent));
564+
if (err)
565+
goto out;
562566

563-
if (!err) {
564-
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
567+
rinfo = &req->r_reply_info;
568+
if (!IS_ENCRYPTED(dir)) {
565569
memcpy(name, rinfo->dname, rinfo->dname_len);
566570
name[rinfo->dname_len] = 0;
567-
dout("get_name %p ino %llx.%llx name %s\n",
568-
child, ceph_vinop(inode), name);
569571
} else {
570-
dout("get_name %p ino %llx.%llx err %d\n",
571-
child, ceph_vinop(inode), err);
572-
}
572+
struct fscrypt_str oname = FSTR_INIT(NULL, 0);
573+
struct ceph_fname fname = { .dir = dir,
574+
.name = rinfo->dname,
575+
.ctext = rinfo->altname,
576+
.name_len = rinfo->dname_len,
577+
.ctext_len = rinfo->altname_len };
578+
579+
err = ceph_fname_alloc_buffer(dir, &oname);
580+
if (err < 0)
581+
goto out;
573582

583+
err = ceph_fname_to_usr(&fname, NULL, &oname, NULL);
584+
if (!err) {
585+
memcpy(name, oname.name, oname.len);
586+
name[oname.len] = 0;
587+
}
588+
ceph_fname_free_buffer(dir, &oname);
589+
}
590+
out:
591+
dout("get_name %p ino %llx.%llx err %d %s%s\n",
592+
child, ceph_vinop(inode), err,
593+
err ? "" : "name ", err ? "" : name);
574594
ceph_mdsc_put_request(req);
575595
return err;
576596
}

fs/ceph/inode.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,17 +1406,36 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
14061406
if (dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME &&
14071407
test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) &&
14081408
!test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
1409+
bool is_nokey = false;
14091410
struct qstr dname;
14101411
struct dentry *dn, *parent;
1412+
struct fscrypt_str oname = FSTR_INIT(NULL, 0);
1413+
struct ceph_fname fname = { .dir = dir,
1414+
.name = rinfo->dname,
1415+
.ctext = rinfo->altname,
1416+
.name_len = rinfo->dname_len,
1417+
.ctext_len = rinfo->altname_len };
14111418

14121419
BUG_ON(!rinfo->head->is_target);
14131420
BUG_ON(req->r_dentry);
14141421

14151422
parent = d_find_any_alias(dir);
14161423
BUG_ON(!parent);
14171424

1418-
dname.name = rinfo->dname;
1419-
dname.len = rinfo->dname_len;
1425+
err = ceph_fname_alloc_buffer(dir, &oname);
1426+
if (err < 0) {
1427+
dput(parent);
1428+
goto done;
1429+
}
1430+
1431+
err = ceph_fname_to_usr(&fname, NULL, &oname, &is_nokey);
1432+
if (err < 0) {
1433+
dput(parent);
1434+
ceph_fname_free_buffer(dir, &oname);
1435+
goto done;
1436+
}
1437+
dname.name = oname.name;
1438+
dname.len = oname.len;
14201439
dname.hash = full_name_hash(parent, dname.name, dname.len);
14211440
tvino.ino = le64_to_cpu(rinfo->targeti.in->ino);
14221441
tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
@@ -1431,9 +1450,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
14311450
dname.len, dname.name, dn);
14321451
if (!dn) {
14331452
dput(parent);
1453+
ceph_fname_free_buffer(dir, &oname);
14341454
err = -ENOMEM;
14351455
goto done;
14361456
}
1457+
if (is_nokey) {
1458+
spin_lock(&dn->d_lock);
1459+
dn->d_flags |= DCACHE_NOKEY_NAME;
1460+
spin_unlock(&dn->d_lock);
1461+
}
14371462
err = 0;
14381463
} else if (d_really_is_positive(dn) &&
14391464
(ceph_ino(d_inode(dn)) != tvino.ino ||
@@ -1445,6 +1470,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
14451470
dput(dn);
14461471
goto retry_lookup;
14471472
}
1473+
ceph_fname_free_buffer(dir, &oname);
14481474

14491475
req->r_dentry = dn;
14501476
dput(parent);

0 commit comments

Comments
 (0)