mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
ceph: add helpers for converting names for userland presentation
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. [ xiubli: fix resulting name length check -- neither name_len nor ctext_len should exceed NAME_MAX ] 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>
This commit is contained in:
parent
c526760181
commit
457117f077
|
|
@ -244,3 +244,80 @@ int ceph_encode_encrypted_fname(const struct inode *parent,
|
||||||
dout("base64-encoded ciphertext name = %.*s\n", elen, buf);
|
dout("base64-encoded ciphertext name = %.*s\n", elen, buf);
|
||||||
return elen;
|
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 > NAME_MAX || fname->ctext_len > 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 = ceph_base64_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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ struct ceph_fs_client;
|
||||||
struct ceph_acl_sec_ctx;
|
struct ceph_acl_sec_ctx;
|
||||||
struct ceph_mds_request;
|
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 {
|
struct ceph_fscrypt_auth {
|
||||||
__le32 cfa_version;
|
__le32 cfa_version;
|
||||||
__le32 cfa_blob_len;
|
__le32 cfa_blob_len;
|
||||||
|
|
@ -71,6 +79,24 @@ void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req,
|
||||||
int ceph_encode_encrypted_fname(const struct inode *parent,
|
int ceph_encode_encrypted_fname(const struct inode *parent,
|
||||||
struct dentry *dentry, char *buf);
|
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 */
|
#else /* CONFIG_FS_ENCRYPTION */
|
||||||
|
|
||||||
static inline void ceph_fscrypt_set_ops(struct super_block *sb)
|
static inline void ceph_fscrypt_set_ops(struct super_block *sb)
|
||||||
|
|
@ -100,6 +126,26 @@ static inline int ceph_encode_encrypted_fname(const struct inode *parent,
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
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 /* CONFIG_FS_ENCRYPTION */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user