Whamcloud - gitweb
LU-18096 enc: ll_get_symlink overlay function 68/56568/5
authorSebastien Buisson <sbuisson@ddn.com>
Wed, 2 Oct 2024 16:33:20 +0000 (18:33 +0200)
committerOleg Drokin <green@whamcloud.com>
Fri, 11 Oct 2024 20:39:04 +0000 (20:39 +0000)
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 <sbuisson@ddn.com>
Change-Id: I141a89d43f392dd4782e148590bc324ea252c2af
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56568
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/crypto.c
lustre/llite/llite_internal.h
lustre/llite/symlink.c

index 1bb45ce..32fcd5b 100644 (file)
@@ -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
index c57d486..9515d55 100644 (file)
@@ -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,
index d9d081d..19a7402 100644 (file)
@@ -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;