On Mon, Sep 14, 2020 at 03:17:05PM -0400, Jeff Layton wrote: > Add helper functions for buffer management and for decrypting filenames > returned by the MDS. Wire those into the readdir codepaths. > > Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> > --- > fs/ceph/crypto.c | 47 +++++++++++++++++++++++++++++++++++++++ > fs/ceph/crypto.h | 35 +++++++++++++++++++++++++++++ > fs/ceph/dir.c | 58 +++++++++++++++++++++++++++++++++++++++--------- > fs/ceph/inode.c | 31 +++++++++++++++++++++++--- > 4 files changed, 157 insertions(+), 14 deletions(-) > > diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c > index f037a4939026..e3038c88c7a0 100644 > --- a/fs/ceph/crypto.c > +++ b/fs/ceph/crypto.c > @@ -107,3 +107,50 @@ int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, > ceph_pagelist_release(pagelist); > return ret; > } > + > +int ceph_fname_to_usr(struct inode *parent, char *name, u32 len, > + struct fscrypt_str *tname, struct fscrypt_str *oname, > + bool *is_nokey) > +{ > + int ret, declen; > + u32 save_len; > + struct fscrypt_str myname = FSTR_INIT(NULL, 0); > + > + if (!IS_ENCRYPTED(parent)) { > + oname->name = name; > + oname->len = len; > + return 0; > + } > + > + ret = fscrypt_get_encryption_info(parent); > + if (ret) > + return ret; > + > + if (tname) { > + save_len = tname->len; > + } else { > + int err; > + > + save_len = 0; > + err = fscrypt_fname_alloc_buffer(NAME_MAX, &myname); > + if (err) > + return err; > + tname = &myname; The 'err' variable isn't needed, since 'ret' can be used instead. > + } > + > + declen = fscrypt_base64_decode(name, len, tname->name); > + if (declen < 0 || declen > NAME_MAX) { > + ret = -EIO; > + goto out; > + } declen <= 0, to cover the empty name case. Also, is there a point in checking for > NAME_MAX? > + > + tname->len = declen; > + > + ret = fscrypt_fname_disk_to_usr(parent, 0, 0, tname, oname, is_nokey); > + > + if (save_len) > + tname->len = save_len; This logic for temporarily overwriting the length is weird. How about something like the following instead: int ceph_fname_to_usr(struct inode *parent, char *name, u32 len, struct fscrypt_str *tname, struct fscrypt_str *oname, bool *is_nokey) { int err, declen; struct fscrypt_str _tname = FSTR_INIT(NULL, 0); struct fscrypt_str iname; if (!IS_ENCRYPTED(parent)) { oname->name = name; oname->len = len; return 0; } err = fscrypt_get_encryption_info(parent); if (err) return err; if (!tname) { err = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname); if (err) return err; tname = &_tname; } declen = fscrypt_base64_decode(name, len, tname->name); if (declen <= 0) { err = -EIO; goto out; } iname.name = tname->name; iname.len = declen; err = fscrypt_fname_disk_to_usr(parent, 0, 0, &iname, oname, is_nokey); out: fscrypt_fname_free_buffer(&_tname); return err; }