Skip to content

Commit

Permalink
ceph: add helpers for converting names for userland presentation
Browse files Browse the repository at this point in the history
Define a new ceph_fname struct that we can use to carry information
about encrypted dentry names. Add helpers for working with these
objects, including ceph_fname_to_usr which formats an encrypted filename
for userland presentation.

Reviewed-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
  • Loading branch information
jtlayton authored and idryomov committed Feb 26, 2023
1 parent 978c8d5 commit 44947f4
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
76 changes: 76 additions & 0 deletions fs/ceph/crypto.c
Expand Up @@ -234,3 +234,79 @@ int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentr
dout("base64-encoded ciphertext name = %.*s\n", elen, buf);
return elen;
}

/**
* ceph_fname_to_usr - convert a filename for userland presentation
* @fname: ceph_fname to be converted
* @tname: temporary name buffer to use for conversion (may be NULL)
* @oname: where converted name should be placed
* @is_nokey: set to true if key wasn't available during conversion (may be NULL)
*
* Given a filename (usually from the MDS), format it for presentation to
* userland. If @parent is not encrypted, just pass it back as-is.
*
* Otherwise, base64 decode the string, and then ask fscrypt to format it
* for userland presentation.
*
* Returns 0 on success or negative error code on error.
*/
int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
struct fscrypt_str *oname, bool *is_nokey)
{
int ret;
struct fscrypt_str _tname = FSTR_INIT(NULL, 0);
struct fscrypt_str iname;

if (!IS_ENCRYPTED(fname->dir)) {
oname->name = fname->name;
oname->len = fname->name_len;
return 0;
}

/* Sanity check that the resulting name will fit in the buffer */
if (fname->name_len > FSCRYPT_BASE64URL_CHARS(NAME_MAX))
return -EIO;

ret = __fscrypt_prepare_readdir(fname->dir);
if (ret)
return ret;

/*
* Use the raw dentry name as sent by the MDS instead of
* generating a nokey name via fscrypt.
*/
if (!fscrypt_has_encryption_key(fname->dir)) {
memcpy(oname->name, fname->name, fname->name_len);
oname->len = fname->name_len;
if (is_nokey)
*is_nokey = true;
return 0;
}

if (fname->ctext_len == 0) {
int declen;

if (!tname) {
ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname);
if (ret)
return ret;
tname = &_tname;
}

declen = fscrypt_base64url_decode(fname->name, fname->name_len, tname->name);
if (declen <= 0) {
ret = -EIO;
goto out;
}
iname.name = tname->name;
iname.len = declen;
} else {
iname.name = fname->ctext;
iname.len = fname->ctext_len;
}

ret = fscrypt_fname_disk_to_usr(fname->dir, 0, 0, &iname, oname);
out:
fscrypt_fname_free_buffer(&_tname);
return ret;
}
41 changes: 41 additions & 0 deletions fs/ceph/crypto.h
Expand Up @@ -13,6 +13,14 @@ struct ceph_fs_client;
struct ceph_acl_sec_ctx;
struct ceph_mds_request;

struct ceph_fname {
struct inode *dir;
char *name; // b64 encoded, possibly hashed
unsigned char *ctext; // binary crypttext (if any)
u32 name_len; // length of name buffer
u32 ctext_len; // length of crypttext
};

struct ceph_fscrypt_auth {
__le32 cfa_version;
__le32 cfa_blob_len;
Expand Down Expand Up @@ -69,6 +77,22 @@ int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode,
void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, struct ceph_acl_sec_ctx *as);
int ceph_encode_encrypted_fname(const struct inode *parent, struct dentry *dentry, char *buf);

static inline int ceph_fname_alloc_buffer(struct inode *parent, struct fscrypt_str *fname)
{
if (!IS_ENCRYPTED(parent))
return 0;
return fscrypt_fname_alloc_buffer(NAME_MAX, fname);
}

static inline void ceph_fname_free_buffer(struct inode *parent, struct fscrypt_str *fname)
{
if (IS_ENCRYPTED(parent))
fscrypt_fname_free_buffer(fname);
}

int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
struct fscrypt_str *oname, bool *is_nokey);

#else /* CONFIG_FS_ENCRYPTION */

static inline void ceph_fscrypt_set_ops(struct super_block *sb)
Expand Down Expand Up @@ -97,6 +121,23 @@ static inline int ceph_encode_encrypted_fname(const struct inode *parent,
{
return -EOPNOTSUPP;
}

static inline int ceph_fname_alloc_buffer(struct inode *parent, struct fscrypt_str *fname)
{
return 0;
}

static inline void ceph_fname_free_buffer(struct inode *parent, struct fscrypt_str *fname)
{
}

static inline int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
struct fscrypt_str *oname, bool *is_nokey)
{
oname->name = fname->name;
oname->len = fname->name_len;
return 0;
}
#endif /* CONFIG_FS_ENCRYPTION */

#endif

0 comments on commit 44947f4

Please sign in to comment.