Whamcloud - gitweb
LU-15420 llite: use op_data to store context states 53/56353/10
authorJames Simmons <jsimmons@infradead.org>
Mon, 2 Dec 2024 16:40:03 +0000 (09:40 -0700)
committerOleg Drokin <green@whamcloud.com>
Sun, 2 Feb 2025 06:25:31 +0000 (06:25 +0000)
The function ll_lookup_it() uses pointers to both secctx
and encctx states since that data can either come from the
server or is created locally on the client. Here we move
the code to use the pointer already in the struct md_op_data.
The reason for this change is that the fscrypt API needs
this information when setting a encrypted context.

Change-Id: Ia46ef093beb08a960fda6493326c92fd905b02f9
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56353
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Timothy Day <timday@amazon.com>
lustre/include/lustre_crypto.h
lustre/include/obd.h
lustre/llite/crypto.c
lustre/llite/llite_lib.c
lustre/llite/namei.c

index 7f3453e..885eeac 100644 (file)
@@ -173,7 +173,6 @@ static inline bool llcrypt_is_nokey_name(const struct dentry *dentry)
 struct ll_sb_info;
 int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
                    bool preload);
-void llcrypt_free_ctx(void *encctx, __u32 size);
 bool ll_sb_has_test_dummy_encryption(struct super_block *sb);
 bool ll_sbi_has_encrypt(struct ll_sb_info *sbi);
 void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set);
index 558e8df..123c991 100644 (file)
@@ -901,6 +901,8 @@ enum md_op_flags {
        MF_QOS_MKDIR            = BIT(6),
        MF_RR_MKDIR             = BIT(7),
        MF_OPNAME_KMALLOCED     = BIT(8),
+       MF_SERVER_ENCCTX        = BIT(9),
+       MF_SERVER_SECCTX        = BIT(10),
 };
 
 enum md_cli_flags {
index ded950e..67441a5 100644 (file)
@@ -128,11 +128,6 @@ int ll_file_open_encrypt(struct inode *inode, struct file *filp)
        return rc;
 }
 
-void llcrypt_free_ctx(void *encctx, __u32 size)
-{
-       OBD_FREE(encctx, size);
-}
-
 #ifdef HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED
 bool ll_sb_has_test_dummy_encryption(struct super_block *sb)
 {
index f5965c5..7800bf6 100644 (file)
@@ -3993,15 +3993,27 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
 void ll_finish_md_op_data(struct md_op_data *op_data)
 {
        ll_unlock_md_op_lsm(op_data);
-       ll_security_release_secctx(op_data->op_file_secctx,
-                                  op_data->op_file_secctx_size,
-                                  op_data->op_file_secctx_slot);
+       /* free selinux context */
+       if (!(op_data->op_flags & MF_SERVER_SECCTX))
+               ll_security_release_secctx(op_data->op_file_secctx,
+                                          op_data->op_file_secctx_size,
+                                          op_data->op_file_secctx_slot);
+       op_data->op_file_secctx_size = 0;
+       op_data->op_file_secctx_slot = 0;
+       op_data->op_file_secctx = NULL;
+
        if (op_data->op_flags & MF_OPNAME_KMALLOCED)
                /* allocated via ll_setup_filename called
                 * from ll_prep_md_op_data
                 */
                kfree(op_data->op_name);
-       llcrypt_free_ctx(op_data->op_file_encctx, op_data->op_file_encctx_size);
+
+       /* free fscrypt context */
+       if (!(op_data->op_flags & MF_SERVER_ENCCTX))
+               OBD_FREE(op_data->op_file_encctx, op_data->op_file_encctx_size);
+       op_data->op_file_encctx_size = 0;
+       op_data->op_file_encctx = NULL;
+
        OBD_FREE_PTR(op_data);
 }
 
index c0474ab..f8f5d32 100644 (file)
@@ -41,9 +41,8 @@
 #endif
 
 static int ll_create_it(struct inode *dir, struct dentry *dentry,
-                       struct lookup_intent *it,
-                       void *secctx, __u32 secctxlen, bool encrypt,
-                       void *encctx, __u32 encctxlen, unsigned int open_flags);
+                       struct lookup_intent *it, struct md_op_data *op_data,
+                       bool encrypt, unsigned int open_flags);
 
 /* called from iget5_locked->find_inode() under inode_lock spinlock */
 static int ll_test_inode(struct inode *inode, void *opaque)
@@ -640,8 +639,7 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
 static int ll_lookup_it_finish(struct ptlrpc_request *request,
                               struct lookup_intent *it,
                               struct inode *parent, struct dentry **de,
-                              void *secctx, __u32 secctxlen,
-                              void *encctx, __u32 encctxlen,
+                              struct md_op_data *op_data,
                               ktime_t kstart, bool encrypt)
 {
        struct inode             *inode = NULL;
@@ -669,29 +667,33 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                 * inode now to save an extra getxattr and avoid deadlock.
                 */
                if (body->mbo_valid & OBD_MD_ENCCTX) {
-                       encctx = req_capsule_server_get(pill, &RMF_FILE_ENCCTX);
-                       encctxlen = req_capsule_get_size(pill,
-                                                        &RMF_FILE_ENCCTX,
-                                                        RCL_SERVER);
+                       void *encctx = req_capsule_server_get(pill,
+                                                             &RMF_FILE_ENCCTX);
+                       u32 encctxlen = req_capsule_get_size(pill,
+                                                            &RMF_FILE_ENCCTX,
+                                                            RCL_SERVER);
 
                        if (encctxlen) {
                                CDEBUG(D_SEC,
                                       "server returned encryption ctx for "DFID"\n",
                                       PFID(ll_inode2fid(inode)));
+
+                               OBD_FREE(op_data->op_file_encctx,
+                                        op_data->op_file_encctx_size);
+
+                               /* Replace local with remote encrypt context */
+                               op_data->op_file_encctx_size = encctxlen;
+                               op_data->op_file_encctx = encctx;
+                               op_data->op_flags |= MF_SERVER_ENCCTX;
+
                                rc = ll_xattr_cache_insert(inode,
                                                           xattr_for_enc(inode),
-                                                          encctx, encctxlen);
+                                                          op_data->op_file_encctx,
+                                                          op_data->op_file_encctx_size);
                                if (rc)
                                        CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n",
                                              ll_i2sbi(inode)->ll_fsname,
                                              PFID(ll_inode2fid(inode)), rc);
-                               else if (encrypt) {
-                                       rc = llcrypt_prepare_readdir(inode);
-                                       if (rc)
-                                               CDEBUG(D_SEC,
-                                                "cannot get enc info for "DFID": rc = %d\n",
-                                                PFID(ll_inode2fid(inode)), rc);
-                               }
                        }
                }
 
@@ -716,19 +718,31 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                 * and avoid deadlock.
                 */
                if (body->mbo_valid & OBD_MD_SECCTX) {
-                       secctx = req_capsule_server_get(pill, &RMF_FILE_SECCTX);
-                       secctxlen = req_capsule_get_size(pill,
-                                                          &RMF_FILE_SECCTX,
-                                                          RCL_SERVER);
+                       void *secctx = req_capsule_server_get(pill,
+                                                             &RMF_FILE_SECCTX);
+                       u32 secctxlen = req_capsule_get_size(pill,
+                                                            &RMF_FILE_SECCTX,
+                                                            RCL_SERVER);
 
-                       if (secctxlen)
+                       if (secctxlen) {
                                CDEBUG(D_SEC, "server returned security context for "
                                       DFID"\n",
                                       PFID(ll_inode2fid(inode)));
+
+                               OBD_FREE(op_data->op_file_secctx,
+                                        op_data->op_file_secctx_size);
+
+                               /* Replace local with remote encrypt context */
+                               op_data->op_file_secctx_size = secctxlen;
+                               op_data->op_file_secctx = secctx;
+                               op_data->op_flags |= MF_SERVER_SECCTX;
+                       }
                }
 
                /* resume normally on error */
-               ll_inode_notifysecctx(inode, secctx, secctxlen);
+               if (!it_disposition(it, DISP_OPEN_CREATE))
+                       ll_inode_notifysecctx(inode, op_data->op_file_secctx,
+                                             op_data->op_file_secctx_size);
        }
 
        /* Only hash *de if it is unhashed (new dentry).
@@ -968,11 +982,6 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
        struct llcrypt_name fname;
        bool encrypt = false;
        struct lu_fid fid;
-       void *secctx = NULL;
-       u32 secctxlen = 0;
-       int secctxslot = 0;
-       void *encctx = NULL;
-       u32 encctxlen = 0;
        u32 opc;
        int rc;
 
@@ -1060,11 +1069,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                                             &op_data->op_file_secctx_slot);
                if (rc < 0)
                        GOTO(out, retval = ERR_PTR(rc));
-
-               secctx = op_data->op_file_secctx;
-               secctxlen = op_data->op_file_secctx_size;
-               secctxslot = op_data->op_file_secctx_slot;
        }
+
        if (it->it_op & IT_CREAT && encrypt) {
                if (unlikely(filename_is_volatile(dentry->d_name.name,
                                                  dentry->d_name.len, NULL))) {
@@ -1135,8 +1141,6 @@ inherit:
                        if (rc)
                                GOTO(out, retval = ERR_PTR(rc));
                }
-               encctx = op_data->op_file_encctx;
-               encctxlen = op_data->op_file_encctx_size;
        }
 
        /* ask for security context upon intent:
@@ -1180,8 +1184,7 @@ inherit:
 
        /* dir layout may change */
        ll_unlock_md_op_lsm(op_data);
-       rc = ll_lookup_it_finish(req, it, parent, &dentry,
-                                secctx, secctxlen, encctx, encctxlen,
+       rc = ll_lookup_it_finish(req, it, parent, &dentry, op_data,
                                 kstart, encrypt);
        if (rc != 0) {
                ll_intent_release(it);
@@ -1190,21 +1193,18 @@ inherit:
 
        if (it_disposition(it, DISP_OPEN_CREATE)) {
                /* Dentry instantiated in ll_create_it. */
-               rc = ll_create_it(parent, dentry, it, secctx, secctxlen,
-                                 encrypt, encctx, encctxlen,
+               rc = ll_create_it(parent, dentry, it, op_data, encrypt,
                                  open_flags);
-               ll_security_release_secctx(secctx, secctxlen,
-                                          secctxslot);
-               llcrypt_free_ctx(encctx, encctxlen);
                if (rc < 0) {
                        ll_intent_release(it);
                        GOTO(out, retval = ERR_PTR(rc));
                }
-       } else if (open_flags & O_CREAT && encrypt &&
+       } else if (encrypt && (open_flags & O_CREAT) &&
                   d_inode(dentry)) {
-               rc = ll_set_encflags(dentry->d_inode, encctx,
-                                    encctxlen, true);
-               llcrypt_free_ctx(encctx, encctxlen);
+               rc = ll_set_encflags(d_inode(dentry),
+                                    op_data->op_file_encctx,
+                                    op_data->op_file_encctx_size,
+                                    true);
                if (rc < 0) {
                        ll_intent_release(it);
                        GOTO(out, retval = ERR_PTR(rc));
@@ -1219,24 +1219,8 @@ inherit:
        ll_lookup_finish_locks(it, dentry);
 
        GOTO(out, retval = (dentry == save) ? NULL : dentry);
-
 out:
        if (!IS_ERR_OR_NULL(op_data)) {
-               if (secctx && secctxlen != 0) {
-                       /* caller needs sec ctx info, so reset it in op_data to
-                        * prevent it from being freed
-                        */
-                       op_data->op_file_secctx = NULL;
-                       op_data->op_file_secctx_size = 0;
-               }
-               if (encctx && encctxlen != 0 &&
-                   it->it_op & IT_CREAT && encrypt) {
-                       /* caller needs enc ctx info, so reset it in op_data to
-                        * prevent it from being freed
-                        */
-                       op_data->op_file_encctx = NULL;
-                       op_data->op_file_encctx_size = 0;
-               }
                llcrypt_free_filename(&fname);
                ll_finish_md_op_data(op_data);
        }
@@ -1534,9 +1518,8 @@ out:
  * with d_instantiate().
  */
 static int ll_create_it(struct inode *dir, struct dentry *dentry,
-                       struct lookup_intent *it,
-                       void *secctx, __u32 secctxlen, bool encrypt,
-                       void *encctx, __u32 encctxlen, unsigned int open_flags)
+                       struct lookup_intent *it, struct md_op_data *op_data,
+                       bool encrypt, unsigned int open_flags)
 {
        struct inode *inode;
        __u64 bits = 0;
@@ -1559,7 +1542,8 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry,
         * security_d_instantiate, which means a getxattr if security
         * context is not set yet
         */
-       rc = ll_inode_notifysecctx(inode, secctx, secctxlen);
+       rc = ll_inode_notifysecctx(inode, op_data->op_file_secctx,
+                                  op_data->op_file_secctx_size);
        if (rc)
                RETURN(rc);
 
@@ -1577,7 +1561,8 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry,
                    (open_flags & O_CIPHERTEXT) == O_CIPHERTEXT &&
                    open_flags & O_DIRECT)
                        preload = false;
-               rc = ll_set_encflags(inode, encctx, encctxlen, preload);
+               rc = ll_set_encflags(inode, op_data->op_file_encctx,
+                                    op_data->op_file_encctx_size, preload);
                if (rc)
                        RETURN(rc);
        }