Whamcloud - gitweb
LU-12275 sec: atomicity of encryption context getting/setting 30/38430/26
authorSebastien Buisson <sbuisson@ddn.com>
Thu, 30 Apr 2020 15:23:00 +0000 (15:23 +0000)
committerOleg Drokin <green@whamcloud.com>
Mon, 20 Jul 2020 05:18:42 +0000 (05:18 +0000)
Encryption layer needs to set an encryption context on files and dirs
that are encrypted. This context is stored as an extended attribute,
that then needs to be fetched upon metadata ops like lookup, getattr,
open, truncate, and layout.

With this patch we send encryption context to the MDT along with
create RPCs. This closes the insecure window between creation and
setting of the encryption context, and saves a setxattr request.

This patch also introduces a way to have the MDT return encryption
context upon granted lock reply, making the encryption context
retrieval atomic, and sparing the client an additional getxattr
request.

Test-Parameters: testlist=sanity-sec envdefinitions=ONLY="36 37 38 39 40 41 42 43 44 45 46 47 48 49" clientdistro=el8.1 fstype=ldiskfs mdscount=2 mdtcount=4
Test-Parameters: testlist=sanity-sec envdefinitions=ONLY="36 37 38 39 40 41 42 43 44 45 46 47 48 49" clientdistro=el8.1 fstype=zfs mdscount=2 mdtcount=4
Test-Parameters: clientversion=2.12 env=SANITY_EXCEPT="27M 56ra 151 156 802"
Test-Parameters: serverversion=2.12 env=SANITY_EXCEPT="56oc 56od 165a 165b 165d 205b"
Test-Parameters: serverversion=2.12 clientdistro=el8.1 env=SANITYN_EXCEPT=106,SANITY_EXCEPT="56oc 56od 165a 165b 165d 205b"
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I45599cdff13d5587103aff6edd699abcda6cb8f4
Reviewed-on: https://review.whamcloud.com/38430
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Mike Pershin <mpershin@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
28 files changed:
lustre/include/lustre_crypto.h
lustre/include/lustre_export.h
lustre/include/lustre_req_layout.h
lustre/include/md_object.h
lustre/include/obd.h
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/llite/crypto.c
lustre/llite/dir.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/namei.c
lustre/llite/xattr_cache.c
lustre/mdc/mdc_internal.h
lustre/mdc/mdc_lib.c
lustre/mdc/mdc_locks.c
lustre/mdc/mdc_reint.c
lustre/mdc/mdc_request.c
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_open.c
lustre/ptlrpc/layout.c
lustre/ptlrpc/wiretest.c
lustre/tests/sanity-sec.sh
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index 63f7696..c54dbcf 100644 (file)
@@ -30,6 +30,9 @@
 #define _LUSTRE_CRYPTO_H_
 
 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_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi);
 bool ll_sbi_has_encrypt(struct ll_sb_info *sbi);
 void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set);
index 3ba56cb..7d29455 100644 (file)
@@ -475,6 +475,11 @@ static inline int exp_connect_sepol(struct obd_export *exp)
        return !!(exp_connect_flags2(exp) & OBD_CONNECT2_SELINUX_POLICY);
 }
 
+static inline int exp_connect_encrypt(struct obd_export *exp)
+{
+       return !!(exp_connect_flags2(exp) & OBD_CONNECT2_ENCRYPT);
+}
+
 enum {
        /* archive_ids in array format */
        KKUC_CT_DATA_ARRAY_MAGIC        = 0x092013cea,
index e311754..bbdc90b 100644 (file)
@@ -59,7 +59,7 @@ enum req_location {
 };
 
 /* Maximal number of fields (buffers) in a request message. */
-#define REQ_MAX_FIELD_NR 11
+#define REQ_MAX_FIELD_NR 12
 
 struct req_capsule {
         struct ptlrpc_request   *rc_req;
@@ -260,6 +260,7 @@ extern struct req_msg_field RMF_CLOSE_DATA;
 extern struct req_msg_field RMF_FILE_SECCTX_NAME;
 extern struct req_msg_field RMF_FILE_SECCTX;
 extern struct req_msg_field RMF_FID_ARRAY;
+extern struct req_msg_field RMF_FILE_ENCCTX;
 
 /*
  * connection handle received in MDS_CONNECT request.
index baafdc4..3ab8a79 100644 (file)
@@ -160,6 +160,10 @@ struct md_op_spec {
        void            *sp_cr_file_secctx; /* xattr value */
        size_t           sp_cr_file_secctx_size; /* xattr value size */
 
+       /* File encryption context for creates. */
+       void            *sp_cr_file_encctx; /* enc ctx value */
+       size_t           sp_cr_file_encctx_size; /* enc ctx size */
+
        /* Archive ID used for auto PCC attach when create newly files. */
        __u32            sp_archive_id;
 
index e72ec06..6ddd0b1 100644 (file)
@@ -914,6 +914,10 @@ struct md_op_data {
        void                   *op_file_secctx;
        __u32                   op_file_secctx_size;
 
+       /* File encryption context, for creates/metadata ops */
+       void                   *op_file_encctx;
+       __u32                   op_file_encctx_size;
+
        __u32                   op_projid;
 
        /* Used by readdir */
index 5e1364d..1a411dd 100644 (file)
@@ -1318,11 +1318,10 @@ lov_mds_md_max_stripe_count(__kernel_size_t buf_size, __u32 lmm_magic)
 #define OBD_MD_FLOSTLAYOUT   (0x0080000000000000ULL) /* contain ost_layout */
 #define OBD_MD_FLPROJID      (0x0100000000000000ULL) /* project ID */
 #define OBD_MD_SECCTX        (0x0200000000000000ULL) /* embed security xattr */
-
 #define OBD_MD_FLLAZYSIZE    (0x0400000000000000ULL) /* Lazy size */
 #define OBD_MD_FLLAZYBLOCKS  (0x0800000000000000ULL) /* Lazy blocks */
-
 #define OBD_MD_FLBTIME       (0x1000000000000000ULL) /* birth time */
+#define OBD_MD_ENCCTX        (0x2000000000000000ULL) /* embed encryption ctx */
 
 #define OBD_MD_FLALLQUOTA (OBD_MD_FLUSRQUOTA | \
                           OBD_MD_FLGRPQUOTA | \
index 84509dd..110928a 100644 (file)
@@ -51,48 +51,77 @@ static int ll_get_context(struct inode *inode, void *ctx, size_t len)
        return rc;
 }
 
+int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
+                   bool preload)
+{
+       unsigned int ext_flags;
+       int rc = 0;
+
+       /* used as encryption unit size */
+       if (S_ISREG(inode->i_mode))
+               inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
+       ext_flags = ll_inode_to_ext_flags(inode->i_flags) | LUSTRE_ENCRYPT_FL;
+       ll_update_inode_flags(inode, ext_flags);
+
+       if (encctx && encctxlen)
+               rc = ll_xattr_cache_insert(inode,
+                                          LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+                                          encctx, encctxlen);
+       if (rc)
+               return rc;
+
+       return preload ? llcrypt_get_encryption_info(inode) : 0;
+}
+
+/* ll_set_context has 2 distinct behaviors, depending on the value of inode
+ * parameter:
+ * - inode is NULL:
+ *   passed fs_data is a struct md_op_data *. We need to store enc ctx in
+ *   op_data, so that it will be sent along to the server with the request that
+ *   the caller is preparing, thus saving a setxattr request.
+ * - inode is not NULL:
+ *   normal case in which passed fs_data is a struct dentry *, letting proceed
+ *   with setxattr operation.
+ *   This use case should only be used when explicitly setting a new encryption
+ *   policy on an existing, empty directory.
+ */
 static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
                          void *fs_data)
 {
-       unsigned int ext_flags;
        struct dentry *dentry;
-       struct md_op_data *op_data;
-       struct ptlrpc_request *req = NULL;
        int rc;
 
-       if (inode == NULL)
-               return 0;
+       if (inode == NULL) {
+               struct md_op_data *op_data = (struct md_op_data *)fs_data;
 
-       ext_flags = ll_inode_to_ext_flags(inode->i_flags) | LUSTRE_ENCRYPT_FL;
-       dentry = (struct dentry *)fs_data;
+               if (!op_data)
+                       return -EINVAL;
+
+               OBD_ALLOC(op_data->op_file_encctx, len);
+               if (op_data->op_file_encctx == NULL)
+                       return -ENOMEM;
+               op_data->op_file_encctx_size = len;
+               memcpy(op_data->op_file_encctx, ctx, len);
+               return 0;
+       }
 
        /* Encrypting the root directory is not allowed */
        if (inode->i_ino == inode->i_sb->s_root->d_inode->i_ino)
                return -EPERM;
 
-       op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
-                                    LUSTRE_OPC_ANY, NULL);
-       if (IS_ERR(op_data))
-               return PTR_ERR(op_data);
-
-       op_data->op_attr_flags = LUSTRE_ENCRYPT_FL;
-       op_data->op_xvalid |= OP_XVALID_FLAGS;
-       rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL, 0, &req);
-       ll_finish_md_op_data(op_data);
-       ptlrpc_req_finished(req);
-       if (rc)
-               return rc;
-
+       dentry = (struct dentry *)fs_data;
        rc = ll_vfs_setxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
                             ctx, len, XATTR_CREATE);
        if (rc)
                return rc;
 
-       /* used as encryption unit size */
-       if (S_ISREG(inode->i_mode))
-               inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
-       ll_update_inode_flags(inode, ext_flags);
-       return 0;
+       return ll_set_encflags(inode, (void *)ctx, len, false);
+}
+
+inline void llcrypt_free_ctx(void *encctx, __u32 size)
+{
+       if (encctx)
+               OBD_FREE(encctx, size);
 }
 
 inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
@@ -142,6 +171,16 @@ const struct llcrypt_operations lustre_cryptops = {
        .max_namelen            = NAME_MAX,
 };
 #else /* !HAVE_LUSTRE_CRYPTO */
+int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
+                   bool preload)
+{
+       return 0;
+}
+
+inline void llcrypt_free_ctx(void *encctx, __u32 size)
+{
+}
+
 inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
 {
        return false;
index a452779..4518d16 100644 (file)
@@ -478,8 +478,9 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
-       if (IS_ENCRYPTED(parent) ||
-           unlikely(llcrypt_dummy_context_enabled(parent))) {
+       if (ll_sbi_has_encrypt(sbi) &&
+           (IS_ENCRYPTED(parent) ||
+           unlikely(llcrypt_dummy_context_enabled(parent)))) {
                err = llcrypt_get_encryption_info(parent);
                if (err)
                        GOTO(out_op_data, err);
@@ -500,6 +501,12 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
                        GOTO(out_op_data, err);
        }
 
+       if (encrypt) {
+               err = llcrypt_inherit_context(parent, NULL, op_data, false);
+               if (err)
+                       GOTO(out_op_data, err);
+       }
+
        op_data->op_cli_flags |= CLI_SET_MEA;
        err = md_create(sbi->ll_md_exp, op_data, lump, len, mode,
                        from_kuid(&init_user_ns, current_fsuid()),
@@ -531,7 +538,8 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
                GOTO(out_inode, err);
 
        if (encrypt) {
-               err = llcrypt_inherit_context(parent, inode, NULL, false);
+               err = ll_set_encflags(inode, op_data->op_file_encctx,
+                                     op_data->op_file_encctx_size, false);
                if (err)
                        GOTO(out_inode, err);
        }
index 93b1a51..cf7683c 100644 (file)
@@ -442,6 +442,11 @@ int ll_xattr_cache_get(struct inode *inode,
                        size_t size,
                        __u64 valid);
 
+int ll_xattr_cache_insert(struct inode *inode,
+                         const char *name,
+                         char *buffer,
+                         size_t size);
+
 static inline bool obd_connect_has_secctx(struct obd_connect_data *data)
 {
 #ifdef CONFIG_SECURITY
index 66b3d2b..45b2128 100644 (file)
@@ -2966,7 +2966,8 @@ void ll_finish_md_op_data(struct md_op_data *op_data)
        ll_unlock_md_op_lsm(op_data);
        security_release_secctx(op_data->op_file_secctx,
                                op_data->op_file_secctx_size);
-        OBD_FREE_PTR(op_data);
+       llcrypt_free_ctx(op_data->op_file_encctx, op_data->op_file_encctx_size);
+       OBD_FREE_PTR(op_data);
 }
 
 int ll_show_options(struct seq_file *seq, struct dentry *dentry)
index f569da1..ed6eb70 100644 (file)
@@ -49,7 +49,8 @@
 
 static int ll_create_it(struct inode *dir, struct dentry *dentry,
                        struct lookup_intent *it,
-                       void *secctx, __u32 secctxlen, bool encrypt);
+                       void *secctx, __u32 secctxlen, bool encrypt,
+                       void *encctx, __u32 encctxlen);
 
 /* called from iget5_locked->find_inode() under inode_lock spinlock */
 static int ll_test_inode(struct inode *inode, void *opaque)
@@ -611,6 +612,7 @@ 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,
                               ktime_t kstart, bool encrypt)
 {
        struct inode             *inode = NULL;
@@ -671,9 +673,33 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                        rc = security_inode_notifysecctx(inode, secctx,
                                                         secctxlen);
                        if (rc)
-                               CWARN("cannot set security context for "
-                                     DFID": rc = %d\n",
-                                     PFID(ll_inode2fid(inode)), rc);
+                               CWARN("%s: cannot set security context for "DFID": rc = %d\n",
+                                     ll_i2sbi(inode)->ll_fsname,
+                                     PFID(ll_inode2fid(inode)),
+                                     rc);
+               }
+
+               /* If encryption context was returned by MDT, put it in
+                * 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);
+
+                       if (encctxlen) {
+                               CDEBUG(D_SEC,
+                                      "server returned encryption ctx for "DFID"\n",
+                                      PFID(ll_inode2fid(inode)));
+                               rc = ll_xattr_cache_insert(inode,
+                                              LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+                                              encctx, encctxlen);
+                               if (rc)
+                                       CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n",
+                                             ll_i2sbi(inode)->ll_fsname,
+                                             PFID(ll_inode2fid(inode)), rc);
+                       }
                }
        }
 
@@ -746,7 +772,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                                   struct lookup_intent *it,
                                   void **secctx, __u32 *secctxlen,
                                   struct pcc_create_attach *pca,
-                                  bool encrypt)
+                                  bool encrypt,
+                                  void **encctx, __u32 *encctxlen)
 {
        ktime_t kstart = ktime_get();
        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
@@ -815,6 +842,20 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                if (secctxlen != NULL)
                        *secctxlen = 0;
        }
+       if (it->it_op & IT_CREAT && encrypt) {
+               rc = llcrypt_inherit_context(parent, NULL, op_data, false);
+               if (rc)
+                       GOTO(out, retval = ERR_PTR(rc));
+               if (encctx != NULL)
+                       *encctx = op_data->op_file_encctx;
+               if (encctxlen != NULL)
+                       *encctxlen = op_data->op_file_encctx_size;
+       } else {
+               if (encctx != NULL)
+                       *encctx = NULL;
+               if (encctxlen != NULL)
+                       *encctxlen = 0;
+       }
 
        /* ask for security context upon intent */
        if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_OPEN)) {
@@ -895,6 +936,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
        rc = ll_lookup_it_finish(req, it, parent, &dentry,
                                 secctx != NULL ? *secctx : NULL,
                                 secctxlen != NULL ? *secctxlen : 0,
+                                encctx != NULL ? *encctx : NULL,
+                                encctxlen != NULL ? *encctxlen : 0,
                                 kstart, encrypt);
        if (rc != 0) {
                ll_intent_release(it);
@@ -918,6 +961,14 @@ out:
                        op_data->op_file_secctx = NULL;
                        op_data->op_file_secctx_size = 0;
                }
+               if (encctx != NULL && encctxlen != NULL &&
+                   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;
+               }
                ll_finish_md_op_data(op_data);
        }
 
@@ -950,7 +1001,8 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,
                itp = NULL;
        else
                itp = &it;
-       de = ll_lookup_it(parent, dentry, itp, NULL, NULL, NULL, false);
+       de = ll_lookup_it(parent, dentry, itp, NULL, NULL, NULL, false,
+                         NULL, NULL);
 
        if (itp != NULL)
                ll_intent_release(itp);
@@ -991,6 +1043,8 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
        long long lookup_flags = LOOKUP_OPEN;
        void *secctx = NULL;
        __u32 secctxlen = 0;
+       void *encctx = NULL;
+       __u32 encctxlen = 0;
        struct ll_sb_info *sbi = NULL;
        struct pcc_create_attach pca = { NULL, NULL };
        bool encrypt = false;
@@ -1048,7 +1102,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
        it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags);
        it->it_flags &= ~MDS_OPEN_FL_INTERNAL;
 
-       if (IS_ENCRYPTED(dir)) {
+       if (ll_sbi_has_encrypt(ll_i2sbi(dir)) && IS_ENCRYPTED(dir)) {
                /* we know that we are going to create a regular file because
                 * we set S_IFREG bit on it->it_create_mode above
                 */
@@ -1062,7 +1116,8 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
        }
 
        /* Dentry added to dcache tree in ll_lookup_it */
-       de = ll_lookup_it(dir, dentry, it, &secctx, &secctxlen, &pca, encrypt);
+       de = ll_lookup_it(dir, dentry, it, &secctx, &secctxlen, &pca, encrypt,
+                         &encctx, &encctxlen);
        if (IS_ERR(de))
                rc = PTR_ERR(de);
        else if (de != NULL)
@@ -1074,8 +1129,9 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
                if (it_disposition(it, DISP_OPEN_CREATE)) {
                        /* Dentry instantiated in ll_create_it. */
                        rc = ll_create_it(dir, dentry, it, secctx, secctxlen,
-                                         encrypt);
+                                         encrypt, encctx, encctxlen);
                        security_release_secctx(secctx, secctxlen);
+                       llcrypt_free_ctx(encctx, encctxlen);
                        if (rc) {
                                /* We dget in ll_splice_alias. */
                                if (de != NULL)
@@ -1106,6 +1162,15 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
                         * already created PCC copy.
                         */
                        pcc_create_attach_cleanup(dir->i_sb, &pca);
+
+                       if (open_flags & O_CREAT && encrypt &&
+                           dentry->d_inode) {
+                               rc = ll_set_encflags(dentry->d_inode, encctx,
+                                                    encctxlen, true);
+                               llcrypt_free_ctx(encctx, encctxlen);
+                               if (rc)
+                                       GOTO(out_release, rc);
+                       }
                }
 
                if (dentry->d_inode && it_disposition(it, DISP_OPEN_OPEN)) {
@@ -1187,7 +1252,8 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it)
  */
 static int ll_create_it(struct inode *dir, struct dentry *dentry,
                        struct lookup_intent *it,
-                       void *secctx, __u32 secctxlen, bool encrypt)
+                       void *secctx, __u32 secctxlen, bool encrypt,
+                       void *encctx, __u32 encctxlen)
 {
        struct inode *inode;
        __u64 bits = 0;
@@ -1222,7 +1288,7 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry,
        d_instantiate(dentry, inode);
 
        if (encrypt) {
-               rc = llcrypt_inherit_context(dir, inode, dentry, true);
+               rc = ll_set_encflags(inode, encctx, encctxlen, true);
                if (rc)
                        RETURN(rc);
        }
@@ -1269,7 +1335,7 @@ static int ll_new_node(struct inode *dir, struct dentry *dchild,
        struct inode *inode = NULL;
        struct ll_sb_info *sbi = ll_i2sbi(dir);
        int tgt_len = 0;
-       int encrypt = 0;
+       bool encrypt = false;
        int err;
 
        ENTRY;
@@ -1291,15 +1357,22 @@ again:
                        GOTO(err_exit, err);
        }
 
-       if ((IS_ENCRYPTED(dir) &&
+       if (ll_sbi_has_encrypt(sbi) &&
+           ((IS_ENCRYPTED(dir) &&
            (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) ||
-           (unlikely(llcrypt_dummy_context_enabled(dir)) && S_ISDIR(mode))) {
+           (unlikely(llcrypt_dummy_context_enabled(dir)) && S_ISDIR(mode)))) {
                err = llcrypt_get_encryption_info(dir);
                if (err)
                        GOTO(err_exit, err);
                if (!llcrypt_has_encryption_key(dir))
                        GOTO(err_exit, err = -ENOKEY);
-               encrypt = 1;
+               encrypt = true;
+       }
+
+       if (encrypt) {
+               err = llcrypt_inherit_context(dir, NULL, op_data, false);
+               if (err)
+                       GOTO(err_exit, err);
        }
 
        err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode,
@@ -1397,7 +1470,8 @@ again:
        d_instantiate(dchild, inode);
 
        if (encrypt) {
-               err = llcrypt_inherit_context(dir, inode, NULL, true);
+               err = ll_set_encflags(inode, op_data->op_file_encctx,
+                                     op_data->op_file_encctx_size, true);
                if (err)
                        GOTO(err_exit, err);
        }
index f1022b0..3489f0b 100644 (file)
@@ -550,3 +550,38 @@ out:
        RETURN(rc);
 }
 
+/**
+ * Insert an xattr value into the cache.
+ *
+ * Add @name xattr with @buffer value and @size length for @inode.
+ * Init cache for @inode if necessary.
+ *
+ * \retval 0       success
+ * \retval < 0    from ll_xattr_cache_add(), except -EPROTO is ignored for
+ *                LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr
+ */
+int ll_xattr_cache_insert(struct inode *inode,
+                         const char *name,
+                         char *buffer,
+                         size_t size)
+{
+       struct ll_inode_info *lli = ll_i2info(inode);
+       int rc;
+
+       ENTRY;
+
+       down_read(&lli->lli_xattrs_list_rwsem);
+       if (!ll_xattr_cache_valid(lli))
+               ll_xattr_cache_init(lli);
+       rc = ll_xattr_cache_add(&lli->lli_xattrs, name, buffer,
+                               size);
+       up_read(&lli->lli_xattrs_list_rwsem);
+
+       if (rc == -EPROTO &&
+           strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0)
+               /* it means enc ctx was already in cache,
+                * ignore error as it cannot be modified
+                */
+               rc = 0;
+       RETURN(rc);
+}
index c037014..43b2065 100644 (file)
@@ -56,6 +56,8 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
 void mdc_file_secctx_pack(struct ptlrpc_request *req,
                          const char *secctx_name,
                          const void *secctx, size_t secctx_size);
+void mdc_file_encctx_pack(struct ptlrpc_request *req,
+                         const void *encctx, size_t encctx_size);
 void mdc_file_sepol_pack(struct ptlrpc_request *req);
 
 void mdc_unlink_pack(struct ptlrpc_request *req, struct md_op_data *op_data);
index 6850357..b44bc0f 100644 (file)
@@ -146,6 +146,23 @@ void mdc_file_secctx_pack(struct ptlrpc_request *req, const char *secctx_name,
        memcpy(buf, secctx, buf_size);
 }
 
+void mdc_file_encctx_pack(struct ptlrpc_request *req,
+                         const void *encctx, size_t encctx_size)
+{
+       void *buf;
+       size_t buf_size;
+
+       if (encctx == NULL)
+               return;
+
+       buf = req_capsule_client_get(&req->rq_pill, &RMF_FILE_ENCCTX);
+       buf_size = req_capsule_get_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+                                       RCL_CLIENT);
+
+       LASSERT(buf_size == encctx_size);
+       memcpy(buf, encctx, buf_size);
+}
+
 void mdc_file_sepol_pack(struct ptlrpc_request *req)
 {
        void *buf;
@@ -216,6 +233,9 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
                             op_data->op_file_secctx,
                             op_data->op_file_secctx_size);
 
+       mdc_file_encctx_pack(req, op_data->op_file_encctx,
+                            op_data->op_file_encctx_size);
+
        /* pack SELinux policy info if any */
        mdc_file_sepol_pack(req);
 }
@@ -296,6 +316,9 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
                                     op_data->op_file_secctx,
                                     op_data->op_file_secctx_size);
 
+               mdc_file_encctx_pack(req, op_data->op_file_encctx,
+                                    op_data->op_file_encctx_size);
+
                /* pack SELinux policy info if any */
                mdc_file_sepol_pack(req);
        }
index 10c1f2c..6699f1c 100644 (file)
@@ -326,6 +326,9 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
        req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT,
                             op_data->op_file_secctx_size);
 
+       req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX, RCL_CLIENT,
+                            op_data->op_file_encctx_size);
+
        /* get SELinux policy info if any */
        rc = sptlrpc_get_sepol(req);
        if (rc < 0) {
@@ -382,6 +385,15 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
                                     RCL_SERVER, 0);
        }
 
+       if (exp_connect_encrypt(exp) && !(it->it_op & IT_CREAT) &&
+           it->it_op & IT_OPEN)
+               req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+                                    RCL_SERVER,
+                                    obd->u.cli.cl_max_mds_easize);
+       else
+               req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+                                    RCL_SERVER, 0);
+
        /**
         * Inline buffer for possible data from Data-on-MDT files.
         */
@@ -462,6 +474,9 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it,
        /* pack the intent */
        lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
        lit->opc = IT_GETXATTR;
+       /* Message below is checked in sanity-selinux test_20d
+        * and sanity-sec test_49
+        */
        CDEBUG(D_INFO, "%s: get xattrs for "DFID"\n",
               exp->exp_obd->obd_name, PFID(&op_data->op_fid1));
 
@@ -576,6 +591,13 @@ mdc_intent_getattr_pack(struct obd_export *exp, struct lookup_intent *it,
                                     RCL_SERVER, 0);
        }
 
+       if (exp_connect_encrypt(exp) && it->it_op & (IT_LOOKUP | IT_GETATTR))
+               req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+                                    RCL_SERVER, easize);
+       else
+               req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+                                    RCL_SERVER, 0);
+
        ptlrpc_request_set_replen(req);
        RETURN(req);
 }
index f32d2fb..c3dbf66 100644 (file)
@@ -210,6 +210,9 @@ rebuild:
        req_capsule_set_size(&req->rq_pill, &RMF_FILE_SECCTX, RCL_CLIENT,
                             op_data->op_file_secctx_size);
 
+       req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX, RCL_CLIENT,
+                            op_data->op_file_encctx_size);
+
        /* get SELinux policy info if any */
        rc = sptlrpc_get_sepol(req);
        if (rc < 0) {
index 0b435d7..6387d98 100644 (file)
@@ -455,7 +455,9 @@ static int mdc_getxattr(struct obd_export *exp, const struct lu_fid *fid,
        LASSERT(obd_md_valid == OBD_MD_FLXATTR ||
                obd_md_valid == OBD_MD_FLXATTRLS);
 
-       /* The below message is checked in sanity-selinux.sh test_20d */
+       /* Message below is checked in sanity-selinux test_20d
+        * and sanity-sec test_49
+        */
        CDEBUG(D_INFO, "%s: get xattr '%s' for "DFID"\n",
               exp->exp_obd->obd_name, name, PFID(fid));
        rc = mdc_xattr_common(exp, &RQF_MDS_GETXATTR, fid, MDS_GETXATTR,
index 8f45fb9..76b54e3 100644 (file)
@@ -2221,6 +2221,16 @@ static int mdd_declare_create_object(const struct lu_env *env,
                if (rc < 0)
                        GOTO(out, rc);
        }
+
+       if (spec->sp_cr_file_encctx != NULL) {
+               buf = mdd_buf_get_const(env, spec->sp_cr_file_encctx,
+                                       spec->sp_cr_file_encctx_size);
+               rc = mdo_declare_xattr_set(env, c, buf,
+                                          LL_XATTR_NAME_ENCRYPTION_CONTEXT, 0,
+                                          handle);
+               if (rc < 0)
+                       GOTO(out, rc);
+       }
 out:
        return rc;
 }
@@ -2442,6 +2452,16 @@ static int mdd_create_object(const struct lu_env *env, struct mdd_object *pobj,
                        GOTO(err_initlized, rc);
        }
 
+       if (spec->sp_cr_file_encctx != NULL) {
+               buf = mdd_buf_get_const(env, spec->sp_cr_file_encctx,
+                                       spec->sp_cr_file_encctx_size);
+               rc = mdo_xattr_set(env, son, buf,
+                                  LL_XATTR_NAME_ENCRYPTION_CONTEXT, 0,
+                                  handle);
+               if (rc < 0)
+                       GOTO(err_initlized, rc);
+       }
+
 err_initlized:
        if (unlikely(rc != 0)) {
                int rc2;
index 5a502f9..1f590af 100644 (file)
@@ -600,8 +600,18 @@ static inline int mdo_declare_xattr_set(const struct lu_env *env,
                                         const char *name,
                                         int fl, struct thandle *handle)
 {
-        struct dt_object *next = mdd_object_child(obj);
-        return dt_declare_xattr_set(env, next, buf, name, fl, handle);
+       struct dt_object *next = mdd_object_child(obj);
+       int rc;
+
+       rc = dt_declare_xattr_set(env, next, buf, name, fl, handle);
+       if (rc >= 0 && strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) {
+               struct lu_attr la = { 0 };
+
+               la.la_valid = LA_FLAGS;
+               la.la_flags = LUSTRE_ENCRYPT_FL;
+               rc = dt_declare_attr_set(env, next, &la, handle);
+       }
+       return rc;
 }
 
 static inline int mdo_xattr_set(const struct lu_env *env,struct mdd_object *obj,
@@ -609,11 +619,20 @@ static inline int mdo_xattr_set(const struct lu_env *env,struct mdd_object *obj,
                                int fl, struct thandle *handle)
 {
        struct dt_object *next = mdd_object_child(obj);
+       int rc;
 
        if (!mdd_object_exists(obj))
                return -ENOENT;
 
-       return dt_xattr_set(env, next, buf, name, fl, handle);
+       rc = dt_xattr_set(env, next, buf, name, fl, handle);
+       if (rc >= 0 && strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) {
+               struct lu_attr la = { 0 };
+
+               la.la_valid = LA_FLAGS;
+               la.la_flags = LUSTRE_ENCRYPT_FL;
+               rc = dt_attr_set(env, next, &la, handle);
+       }
+       return rc;
 }
 
 static inline int mdo_declare_xattr_del(const struct lu_env *env,
index efdbb07..a093a49 100644 (file)
@@ -1913,6 +1913,12 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
                }
 
                rc = mdt_pack_secctx_in_reply(info, child);
+               if (unlikely(rc)) {
+                       mdt_object_unlock(info, child, lhc, 1);
+                       RETURN(rc);
+               }
+
+               rc = mdt_pack_encctx_in_reply(info, child);
                if (unlikely(rc))
                        mdt_object_unlock(info, child, lhc, 1);
                RETURN(rc);
@@ -2107,6 +2113,12 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
                GOTO(out_child, rc);
        }
 
+       rc = mdt_pack_encctx_in_reply(info, child);
+       if (unlikely(rc)) {
+               mdt_object_unlock(info, child, lhc, 1);
+               GOTO(out_child, rc);
+       }
+
        lock = ldlm_handle2lock(&lhc->mlh_reg_lh);
        if (lock) {
                /* Debugging code. */
@@ -2569,17 +2581,27 @@ static void mdt_preset_secctx_size(struct mdt_thread_info *info)
            req_capsule_has_field(pill, &RMF_FILE_SECCTX_NAME,
                                  RCL_CLIENT)) {
                if (req_capsule_get_size(pill, &RMF_FILE_SECCTX_NAME,
-                                        RCL_CLIENT) != 0) {
+                                        RCL_CLIENT) != 0)
                        /* pre-set size in server part with max size */
                        req_capsule_set_size(pill, &RMF_FILE_SECCTX,
                                             RCL_SERVER,
-                                            info->mti_mdt->mdt_max_ea_size);
-               } else {
+                                            OBD_MAX_DEFAULT_EA_SIZE);
+               else
                        req_capsule_set_size(pill, &RMF_FILE_SECCTX,
                                             RCL_SERVER, 0);
-               }
        }
+}
+
+static void mdt_preset_encctx_size(struct mdt_thread_info *info)
+{
+       struct req_capsule *pill = info->mti_pill;
 
+       if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX,
+                                 RCL_SERVER))
+               /* pre-set size in server part with max size */
+               req_capsule_set_size(pill, &RMF_FILE_ENCCTX,
+                                    RCL_SERVER,
+                                    info->mti_mdt->mdt_max_mdsize);
 }
 
 static int mdt_reint_internal(struct mdt_thread_info *info,
@@ -2621,6 +2643,7 @@ static int mdt_reint_internal(struct mdt_thread_info *info,
                                     LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
 
        mdt_preset_secctx_size(info);
+       mdt_preset_encctx_size(info);
 
        rc = req_capsule_server_pack(pill);
        if (rc != 0) {
@@ -3872,6 +3895,7 @@ static int mdt_unpack_req_pack_rep(struct mdt_thread_info *info,
                                             LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
 
                mdt_preset_secctx_size(info);
+               mdt_preset_encctx_size(info);
 
                rc = req_capsule_server_pack(pill);
                if (rc)
index ce00097..8ffa943 100644 (file)
@@ -969,6 +969,8 @@ int mdt_close_internal(struct mdt_thread_info *info, struct ptlrpc_request *req,
                       struct mdt_body *repbody);
 int mdt_pack_secctx_in_reply(struct mdt_thread_info *info,
                             struct mdt_object *child);
+int mdt_pack_encctx_in_reply(struct mdt_thread_info *info,
+                            struct mdt_object *child);
 
 static inline struct mdt_device *mdt_dev(struct lu_device *d)
 {
index 96d4078..f3a0d42 100644 (file)
@@ -795,6 +795,12 @@ int mdt_fix_reply(struct mdt_thread_info *info)
            !(body->mbo_valid & OBD_MD_SECCTX))
                req_capsule_shrink(pill, &RMF_FILE_SECCTX, 0, RCL_SERVER);
 
+       /* Shrink optional ENCCTX buffer if it is not used */
+       if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX, RCL_SERVER) &&
+           req_capsule_get_size(pill, &RMF_FILE_ENCCTX, RCL_SERVER) != 0 &&
+           !(body->mbo_valid & OBD_MD_ENCCTX))
+               req_capsule_shrink(pill, &RMF_FILE_ENCCTX, 0, RCL_SERVER);
+
        /*
         * Some more field should be shrinked if needed.
         * This should be done by those who added fields to reply message.
@@ -1085,6 +1091,28 @@ static int mdt_file_secctx_unpack(struct req_capsule *pill,
        return 0;
 }
 
+static int mdt_file_encctx_unpack(struct req_capsule *pill,
+                                 void **encctx, size_t *encctx_size)
+{
+       *encctx = NULL;
+       *encctx_size = 0;
+
+       if (!exp_connect_encrypt(pill->rc_req->rq_export))
+               return 0;
+
+       if (!req_capsule_has_field(pill, &RMF_FILE_ENCCTX, RCL_CLIENT) ||
+           !req_capsule_field_present(pill, &RMF_FILE_ENCCTX, RCL_CLIENT))
+               return -EPROTO;
+
+       *encctx_size = req_capsule_get_size(pill, &RMF_FILE_ENCCTX, RCL_CLIENT);
+       if (*encctx_size == 0)
+               return 0;
+
+       *encctx = req_capsule_client_get(pill, &RMF_FILE_ENCCTX);
+
+       return 0;
+}
+
 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
 {
        struct lu_ucred *uc = mdt_ucred(info);
@@ -1318,6 +1346,11 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
        if (rc < 0)
                RETURN(rc);
 
+       rc = mdt_file_encctx_unpack(pill, &sp->sp_cr_file_encctx,
+                                   &sp->sp_cr_file_encctx_size);
+       if (rc < 0)
+               RETURN(rc);
+
        rc = req_check_sepol(pill);
        if (rc)
                RETURN(rc);
@@ -1648,6 +1681,11 @@ static int mdt_open_unpack(struct mdt_thread_info *info)
        if (rc < 0)
                RETURN(rc);
 
+       rc = mdt_file_encctx_unpack(pill, &sp->sp_cr_file_encctx,
+                                   &sp->sp_cr_file_encctx_size);
+       if (rc < 0)
+               RETURN(rc);
+
        rc = req_check_sepol(pill);
        if (rc)
                RETURN(rc);
@@ -1963,3 +2001,72 @@ int mdt_is_remote_object(struct mdt_thread_info *info,
 
        RETURN(0);
 }
+
+int mdt_pack_encctx_in_reply(struct mdt_thread_info *info,
+                            struct mdt_object *child)
+{
+       struct lu_buf *buffer;
+       struct mdt_body *repbody;
+       struct req_capsule *pill = info->mti_pill;
+       struct obd_export *exp = mdt_info_req(info)->rq_export;
+       int rc = 0;
+
+       if (!exp_connect_encrypt(exp))
+               return rc;
+
+       if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX, RCL_SERVER) &&
+           req_capsule_get_size(pill, &RMF_FILE_ENCCTX, RCL_SERVER) != 0) {
+               struct lu_attr la = { 0 };
+               struct dt_object *dt = mdt_obj2dt(child);
+
+               if (dt && dt->do_ops && dt->do_ops->do_attr_get)
+                       dt_attr_get(info->mti_env, mdt_obj2dt(child), &la);
+
+               if (la.la_valid & LA_FLAGS && la.la_flags & LUSTRE_ENCRYPT_FL) {
+                       buffer = &info->mti_buf;
+
+                       /* fill reply buffer with encryption context now */
+                       buffer->lb_len =
+                               req_capsule_get_size(pill, &RMF_FILE_ENCCTX,
+                                                    RCL_SERVER);
+                       buffer->lb_buf =
+                               req_capsule_server_get(pill, &RMF_FILE_ENCCTX);
+                       rc = mo_xattr_get(info->mti_env,
+                                         mdt_object_child(child),
+                                         buffer,
+                                         LL_XATTR_NAME_ENCRYPTION_CONTEXT);
+                       if (rc >= 0) {
+                               CDEBUG(D_SEC,
+                                      "found encryption ctx of size %d for "DFID"\n",
+                                      rc, PFID(mdt_object_fid(child)));
+
+                               repbody = req_capsule_server_get(pill,
+                                                                &RMF_MDT_BODY);
+                               repbody->mbo_valid |= OBD_MD_ENCCTX;
+                               if (rc < buffer->lb_len)
+                                       req_capsule_shrink(pill,
+                                                          &RMF_FILE_ENCCTX, rc,
+                                                          RCL_SERVER);
+                               rc = 0;
+                       } else {
+                               CDEBUG(D_SEC,
+                                      "encryption ctx not found for "DFID": rc = %d\n",
+                                      PFID(mdt_object_fid(child)), rc);
+                               req_capsule_shrink(pill, &RMF_FILE_ENCCTX, 0,
+                                                  RCL_SERVER);
+                               /* handling -ENOENT is important because it may
+                                * change object state in DNE env dropping
+                                * LOHA_EXISTS flag, it is important to return
+                                * that to the caller.
+                                * Check LU-13115 for details.
+                                */
+                               if (rc != -ENOENT)
+                                       rc = 0;
+                       }
+               } else {
+                       req_capsule_shrink(pill, &RMF_FILE_ENCCTX, 0,
+                                          RCL_SERVER);
+               }
+       }
+       return rc;
+}
index 5aa5314..9f10fc6 100644 (file)
@@ -1229,6 +1229,10 @@ static int mdt_cross_open(struct mdt_thread_info *info,
                        if (unlikely(rc))
                                GOTO(out, rc);
 
+                       rc = mdt_pack_encctx_in_reply(info, o);
+                       if (unlikely(rc))
+                               GOTO(out, rc);
+
                        rc = mdt_finish_open(info, NULL, o, open_flags, 0, rep);
                } else {
                        /*
@@ -1560,6 +1564,10 @@ int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
        if (unlikely(rc))
                GOTO(out_child, result = rc);
 
+       rc = mdt_pack_encctx_in_reply(info, child);
+       if (unlikely(rc))
+               GOTO(out_child, result = rc);
+
        rc = mdt_check_resent_lock(info, child, lhc);
        if (rc < 0) {
                GOTO(out_child, result = rc);
index 807ad87..40bd630 100644 (file)
@@ -213,7 +213,8 @@ static const struct req_msg_field *mds_reint_create_acl_client[] = {
        &RMF_DLM_REQ,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_create_sym_client[] = {
@@ -225,7 +226,8 @@ static const struct req_msg_field *mds_reint_create_sym_client[] = {
        &RMF_DLM_REQ,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_open_client[] = {
@@ -237,7 +239,8 @@ static const struct req_msg_field *mds_reint_open_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *mds_reint_open_server[] = {
@@ -467,7 +470,8 @@ static const struct req_msg_field *ldlm_intent_open_server[] = {
        &RMF_CAPA1,
        &RMF_CAPA2,
        &RMF_NIOBUF_INLINE,
-       &RMF_FILE_SECCTX
+       &RMF_FILE_SECCTX,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_getattr_client[] = {
@@ -488,7 +492,8 @@ static const struct req_msg_field *ldlm_intent_getattr_server[] = {
        &RMF_ACL,
        &RMF_CAPA1,
        &RMF_FILE_SECCTX,
-       &RMF_DEFAULT_MDT_MD
+       &RMF_DEFAULT_MDT_MD,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_create_client[] = {
@@ -501,7 +506,8 @@ static const struct req_msg_field *ldlm_intent_create_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_open_client[] = {
@@ -515,7 +521,8 @@ static const struct req_msg_field *ldlm_intent_open_client[] = {
        &RMF_EADATA,
        &RMF_FILE_SECCTX_NAME,
        &RMF_FILE_SECCTX,
-       &RMF_SELINUX_POL
+       &RMF_SELINUX_POL,
+       &RMF_FILE_ENCCTX,
 };
 
 static const struct req_msg_field *ldlm_intent_getxattr_client[] = {
@@ -1065,6 +1072,10 @@ struct req_msg_field RMF_FILE_SECCTX =
        DEFINE_MSGF("file_secctx", RMF_F_NO_SIZE_CHECK, -1, NULL, NULL);
 EXPORT_SYMBOL(RMF_FILE_SECCTX);
 
+struct req_msg_field RMF_FILE_ENCCTX =
+       DEFINE_MSGF("file_encctx", RMF_F_NO_SIZE_CHECK, -1, NULL, NULL);
+EXPORT_SYMBOL(RMF_FILE_ENCCTX);
+
 struct req_msg_field RMF_LLOGD_BODY =
         DEFINE_MSGF("llogd_body", 0,
                     sizeof(struct llogd_body), lustre_swab_llogd_body, NULL);
index e31334d..442faf1 100644 (file)
@@ -1635,6 +1635,8 @@ void lustre_assert_wire_constants(void)
                 OBD_MD_FLLAZYSIZE);
        LASSERTF(OBD_MD_FLLAZYBLOCKS == (0x0800000000000000ULL), "found 0x%.16llxULL\n",
                 OBD_MD_FLLAZYBLOCKS);
+       LASSERTF(OBD_MD_ENCCTX == (0x2000000000000000ULL), "found 0x%.16llxULL\n",
+                OBD_MD_ENCCTX);
        BUILD_BUG_ON(OBD_FL_INLINEDATA != 0x00000001);
        BUILD_BUG_ON(OBD_FL_OBDMDEXISTS != 0x00000002);
        BUILD_BUG_ON(OBD_FL_DELORPHAN != 0x00000004);
index 030888c..5f6ea06 100755 (executable)
@@ -3533,6 +3533,61 @@ test_48b() {
 }
 run_test 48b "encrypted file: concurrent truncate"
 
+trace_cmd() {
+       local cmd="$@"
+       local xattr_name="security.c"
+
+       sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
+       $LCTL set_param debug=+info
+       $LCTL clear
+
+       echo $cmd
+       eval $cmd
+
+       $LCTL dk | grep -E "get xattr '${xattr_name}'|get xattrs"
+       [ $? -ne 0 ] || error "get xattr event was triggered"
+}
+
+test_49() {
+       $LCTL get_param mdc.*.import | grep -q client_encryption ||
+               skip "client encryption not supported"
+
+       mount.lustre --help |& grep -q "test_dummy_encryption:" ||
+               skip "need dummy encryption support"
+
+       stack_trap cleanup_for_enc_tests EXIT
+       setup_for_enc_tests
+
+       local dirname=$DIR/$tdir/subdir
+
+       mkdir $dirname
+
+       trace_cmd stat $dirname
+       trace_cmd touch $dirname/f1
+       trace_cmd stat $dirname/f1
+       trace_cmd cat $dirname/f1
+       dd if=/dev/zero of=$dirname/f1 bs=1M count=10 conv=fsync
+       trace_cmd $TRUNCATE $dirname/f1 10240
+       trace_cmd $LFS setstripe -E -1 -S 4M $dirname/f2
+       trace_cmd $LFS migrate -E -1 -S 256K $dirname/f2
+       trace_cmd $LFS setdirstripe -i 1 $dirname/d2
+       trace_cmd $LFS migrate -m 0 $dirname/d2
+
+       $LFS setdirstripe -i 1 -c 1 $dirname/d3
+       dirname=$dirname/d3/subdir
+       mkdir $dirname
+
+       trace_cmd stat $dirname
+       trace_cmd touch $dirname/f1
+       trace_cmd stat $dirname/f1
+       trace_cmd cat $dirname/f1
+       dd if=/dev/zero of=$dirname/f1 bs=1M count=10 conv=fsync
+       trace_cmd $TRUNCATE $dirname/f1 10240
+       trace_cmd $LFS setstripe -E -1 -S 4M $dirname/f2
+       trace_cmd $LFS migrate -E -1 -S 256K $dirname/f2
+}
+run_test 49 "Avoid getxattr for encryption context"
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {
index 5a282a7..dea1149 100644 (file)
@@ -732,6 +732,7 @@ check_obdo(void)
        CHECK_DEFINE_64X(OBD_MD_SECCTX);
        CHECK_DEFINE_64X(OBD_MD_FLLAZYSIZE);
        CHECK_DEFINE_64X(OBD_MD_FLLAZYBLOCKS);
+       CHECK_DEFINE_64X(OBD_MD_ENCCTX);
 
        CHECK_CVALUE_X(OBD_FL_INLINEDATA);
        CHECK_CVALUE_X(OBD_FL_OBDMDEXISTS);
index fe7451c..625cca8 100644 (file)
@@ -1661,6 +1661,8 @@ void lustre_assert_wire_constants(void)
                 OBD_MD_FLLAZYSIZE);
        LASSERTF(OBD_MD_FLLAZYBLOCKS == (0x0800000000000000ULL), "found 0x%.16llxULL\n",
                 OBD_MD_FLLAZYBLOCKS);
+       LASSERTF(OBD_MD_ENCCTX == (0x2000000000000000ULL), "found 0x%.16llxULL\n",
+                OBD_MD_ENCCTX);
        BUILD_BUG_ON(OBD_FL_INLINEDATA != 0x00000001);
        BUILD_BUG_ON(OBD_FL_OBDMDEXISTS != 0x00000002);
        BUILD_BUG_ON(OBD_FL_DELORPHAN != 0x00000004);