From 209607fd79571187722116ede0aed3392bc43618 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Wed, 2 Oct 2024 18:33:20 +0200 Subject: [PATCH] LU-18096 enc: ll_get_symlink overlay function ll_get_symlink() overlay function is necessary to properly encode for presentation the symlink target when the encryption key is not available, in a way that is compatible with the overlay function ll_setup_filename(), so that further readlink without the encryption key works properly. Test-Parameters: testlist=sanity-sec env=ONLY=47,ONLY_REPEAT=10 mdscount=2 mdtcount=4 osscount=1 ostcount=8 clientcount=2 Test-Parameters: testlist=sanity-sec env=ONLY=47,ONLY_REPEAT=10 mdscount=2 mdtcount=4 osscount=1 ostcount=8 clientcount=2 clientdistro=ubuntu2404 serverdistro=el8.8 Signed-off-by: Sebastien Buisson Change-Id: I141a89d43f392dd4782e148590bc324ea252c2af Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56568 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin --- lustre/llite/crypto.c | 52 ++++++++++++++++++++++++++++++++++++++++++- lustre/llite/llite_internal.h | 7 ++++++ lustre/llite/symlink.c | 4 ++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lustre/llite/crypto.c b/lustre/llite/crypto.c index 1bb45ce..32fcd5b 100644 --- a/lustre/llite/crypto.c +++ b/lustre/llite/crypto.c @@ -243,7 +243,7 @@ static int ll_digest_long_name(struct inode *dir, struct llcrypt_name *fname, } digest = (struct ll_digest_filename *)fname->disk_name.name; *fid = digest->ldf_fid; - if (!fid_is_sane(fid)) { + if (!fid_is_sane(fid) && !fid_is_zero(fid)) { rc = -EINVAL; goto out_free; } @@ -461,6 +461,56 @@ int ll_setup_filename(struct inode *dir, const struct qstr *iname, } /** + * ll_get_symlink() - overlay to llcrypt_get_symlink() + * @inode: the symlink inode + * @caddr: the on-disk contents of the symlink + * @max_size: size of @caddr buffer + * @done: if successful, will be set up to free the returned target if needed + * + * This overlay function is necessary to properly encode for presentation the + * symlink target when the encryption key is not available, in a way that is + * compatible with the overlay function ll_setup_filename(), so that further + * readlink without the encryption key works properly. + */ +const char *ll_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct delayed_call *done) +{ + struct llcrypt_str lltr = LLTR_INIT(NULL, 0); + struct llcrypt_str de_name; + struct lu_fid fid; + int rc; + + rc = llcrypt_get_encryption_info(inode); + if (rc) + return ERR_PTR(rc); + + /* If enc key is available, just call llcrypt function. */ + if (llcrypt_has_encryption_key(inode)) + return llcrypt_get_symlink(inode, caddr, max_size, done); + + /* When enc key is not available, we need to build an encoded name to + * userspace that can later be decoded by ll_setup_filename(). + */ + rc = llcrypt_fname_alloc_buffer(inode, NAME_MAX + 1, &lltr); + if (rc < 0) + return ERR_PTR(rc); + + fid_zero(&fid); + de_name.name = (char *)caddr; + de_name.len = max_size; + rc = ll_fname_disk_to_usr(inode, 0, 0, &de_name, &lltr, &fid); + if (rc) { + llcrypt_fname_free_buffer(&lltr); + return ERR_PTR(rc); + } + lltr.name[lltr.len] = '\0'; + + set_delayed_call(done, kfree_link, lltr.name); + return lltr.name; +} + +/** * ll_fname_disk_to_usr() - overlay to llcrypt_fname_disk_to_usr * @inode: the inode to convert name * @hash: major hash for inode diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index c57d486..9515d55 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -2128,6 +2128,13 @@ int ll_prepare_lookup(struct inode *dir, struct dentry *de, int ll_setup_filename(struct inode *dir, const struct qstr *iname, int lookup, struct llcrypt_name *fname, struct lu_fid *fid); +#ifdef CONFIG_LL_ENCRYPTION +const char *ll_get_symlink(struct inode *inode, const void *caddr, + unsigned int max_size, + struct delayed_call *done); +#else +#define ll_get_symlink(inode, caddr, max_size, done) ERR_PTR(-EOPNOTSUPP) +#endif int ll_fname_disk_to_usr(struct inode *inode, u32 hash, u32 minor_hash, struct llcrypt_str *iname, struct llcrypt_str *oname, diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index d9d081d..19a7402 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -120,8 +120,8 @@ static int ll_readlink_internal(struct inode *inode, #ifdef HAVE_IOP_GET_LINK if (IS_ENCRYPTED(inode)) { - const char *target = llcrypt_get_symlink(inode, *symname, - symlen, done); + const char *target = ll_get_symlink(inode, *symname, + symlen, done); if (IS_ERR(target)) RETURN(PTR_ERR(target)); symlen = strlen(target) + 1; -- 1.8.3.1