Whamcloud - gitweb
LU-17907 enc: enc flag should not remove other flags 17/55317/6
authorSebastien Buisson <sbuisson@ddn.com>
Wed, 5 Jun 2024 12:35:02 +0000 (14:35 +0200)
committerOleg Drokin <green@whamcloud.com>
Tue, 25 Jun 2024 03:30:28 +0000 (03:30 +0000)
When updating inode flags, the lli_flags must be taken into account
so that they do not get lost. So provide helper functions for callers
of ll_update_inode_flags(), as an overlay to ll_inode_to_ext_flags().
And on server side, the mdd layer must fetch the existing flags when
setting LUSTRE_ENCRYPT_FL attr flag.

Fixes: 40d91eafe2 ("LU-12275 sec: atomicity of encryption context getting/setting")
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I150f2d87cef112beab81d1d2030133671d4b7361
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55317
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/crypto.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/mdd/mdd_internal.h
lustre/tests/sanity-sec.sh

index 2a92b07..7c87e08 100644 (file)
@@ -55,7 +55,7 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
        /* 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;
+       ext_flags = ll_inode2ext_flags(inode) | LUSTRE_ENCRYPT_FL;
        ll_update_inode_flags(inode, ext_flags);
 
        if (encctx && encctxlen)
index 8ca7720..91aa134 100644 (file)
@@ -129,9 +129,7 @@ static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
                                      ATTR_CTIME);
        op_data->op_xvalid |= OP_XVALID_CTIME_SET;
        op_data->op_attr_blocks = inode->i_blocks;
-       op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
-       if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
-               op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
+       op_data->op_attr_flags = ll_inode2ext_flags(inode);
        op_data->op_open_handle = och->och_open_handle;
 
        if (och->och_flags & FMODE_WRITE &&
@@ -4099,7 +4097,6 @@ int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid)
        struct ptlrpc_request *req = NULL;
        struct md_op_data *op_data;
        struct cl_object *obj;
-       unsigned int inode_flags;
        int rc = 0;
 
        CDEBUG(D_QUOTA, DFID" xflags=%x projid=%u\n",
@@ -4113,10 +4110,7 @@ int ll_set_project(struct inode *inode, __u32 xflags, __u32 projid)
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
-       inode_flags = ll_xflags_to_inode_flags(xflags);
-       op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags);
-       if (xflags & FS_XFLAG_PROJINHERIT)
-               op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
+       op_data->op_attr_flags = ll_xflags_to_ext_flags(xflags);
 
        /* pass projid to md_op_data */
        op_data->op_projid = projid;
index 4e2e6b1..382ef1a 100644 (file)
@@ -518,6 +518,9 @@ enum ll_inode_flags {
        /* Xattr cache is filled */
        LLIF_XATTR_CACHE_FILLED = 7,
 
+/* New flags added to this enum potentially need to be handled in
+ * ll_inode2ext_flags/ll_set_inode_flags
+ */
 };
 
 int ll_xattr_cache_destroy(struct inode *inode);
@@ -1476,6 +1479,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs);
 int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs,
                       u32 flags);
 int ll_update_inode(struct inode *inode, struct lustre_md *md);
+u32 ll_inode2ext_flags(struct inode *inode);
+u32 ll_xflags_to_ext_flags(u32 xflags);
 void ll_update_inode_flags(struct inode *inode, unsigned int ext_flags);
 void ll_update_dir_depth_dmv(struct inode *dir, struct dentry *de);
 int ll_read_inode2(struct inode *inode, void *opaque);
index eda4a01..5f380b8 100644 (file)
@@ -2759,11 +2759,40 @@ int ll_inode_size_trylock(struct inode *inode)
        return mutex_trylock(&lli->lli_size_mutex);
 }
 
+u32 ll_inode2ext_flags(struct inode *inode)
+{
+       u32 ext_flags;
+
+       ext_flags = ll_inode_to_ext_flags(inode->i_flags);
+
+       /* add here future new lli_flags */
+       if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
+               ext_flags |= LUSTRE_PROJINHERIT_FL;
+
+       return ext_flags;
+}
+
+u32 ll_xflags_to_ext_flags(u32 xflags)
+{
+       u32 ext_flags;
+       u32 inode_flags;
+
+       inode_flags = ll_xflags_to_inode_flags(xflags);
+       ext_flags = ll_inode_to_ext_flags(inode_flags);
+       if (xflags & FS_XFLAG_PROJINHERIT)
+               ext_flags |= LUSTRE_PROJINHERIT_FL;
+
+       return ext_flags;
+}
+
 void ll_update_inode_flags(struct inode *inode, unsigned int ext_flags)
 {
        /* do not clear encryption flag */
        ext_flags |= ll_inode_to_ext_flags(inode->i_flags) & LUSTRE_ENCRYPT_FL;
+
        inode->i_flags = ll_ext_to_inode_flags(ext_flags);
+
+       /* add here future new lli_flags */
        if (ext_flags & LUSTRE_PROJINHERIT_FL)
                set_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags);
        else
index 3e61fda..b51b8fa 100644 (file)
@@ -684,8 +684,13 @@ static inline int mdo_xattr_set(const struct lu_env *env,struct mdd_object *obj,
             (rc = mdd_dir_is_empty(env, obj)) == 0)) {
                struct lu_attr la = { 0 };
 
+               /* try to fetch existing attrs, to not lose them */
+               (void)dt_attr_get(env, next, &la);
+               if (la.la_valid & LA_FLAGS)
+                       la.la_flags |= LUSTRE_ENCRYPT_FL;
+               else
+                       la.la_flags = LUSTRE_ENCRYPT_FL;
                la.la_valid = LA_FLAGS;
-               la.la_flags = LUSTRE_ENCRYPT_FL;
                /* if this is an old client using the old enc xattr name,
                 * switch to the new name for consistency
                 */
index b5d31e8..36e247c 100755 (executable)
@@ -6360,6 +6360,68 @@ test_70() {
 }
 run_test 70 "targets have local copy of sptlrpc llog"
 
+test_71() {
+       local vaultdir=$DIR/$tdir/vault
+       local projid=101
+       local res
+
+       (( $MDS1_VERSION >= $(version_code 2.15.63) )) ||
+               skip "Need MDS version at least 2.15.63"
+
+       [[ $($LCTL get_param mdc.*.import) =~ client_encryption ]] ||
+               skip "need encryption support"
+       which fscrypt || skip_env "Need fscrypt"
+
+       mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+
+       yes | fscrypt setup --force --verbose ||
+               echo "fscrypt global setup already done"
+       sed -i 's/\(.*\)policy_version\(.*\):\(.*\)\"[0-9]*\"\(.*\)/\1policy_version\2:\3"2"\4/' \
+               /etc/fscrypt.conf
+       yes | fscrypt setup --verbose $MOUNT ||
+               echo "fscrypt setup $MOUNT already done"
+       stack_trap "rm -rf $MOUNT/.fscrypt"
+
+       mkdir -p $vaultdir
+       stack_trap "rm -rf $vaultdir"
+       $LFS project -p $projid -s $vaultdir
+       $LFS project -d $vaultdir
+       res=$($LFS project -d $vaultdir | awk '{print $1}')
+       [[ "$res" == "$projid" ]] ||
+               error "project id set to $res instead of $projid"
+       res=$($LFS project -d $vaultdir | awk '{print $2}')
+       [[ "$res" == "P" ]] ||
+               error "project id should have inherit flag (1)"
+
+       echo -e 'mypass\nmypass' | fscrypt encrypt --verbose \
+            --source=custom_passphrase --name=protector_71 $vaultdir ||
+               error "fscrypt encrypt $vaultdir failed"
+
+       $LFS project -d $vaultdir
+       res=$($LFS project -d $vaultdir | awk '{print $1}')
+       [[ "$res" == "$projid" ]] ||
+               error "project id changed to $res after enc"
+       res=$($LFS project -d $vaultdir | awk '{print $2}')
+       [[ "$res" == "P" ]] ||
+               error "project id should have inherit flag (2)"
+
+       touch $vaultdir/fileA || error "touch $vaultdir/fileA failed"
+       $LFS project $vaultdir/fileA
+       res=$($LFS project $vaultdir/fileA | awk '{print $1}')
+       [[ "$res" == "$projid" ]] ||
+               error "project id on fileA is $res after enc"
+
+       mkdir $vaultdir/dirA || error "touch $vaultdir/dirA failed"
+       $LFS project -d $vaultdir/dirA
+       res=$($LFS project -d $vaultdir/dirA | awk '{print $1}')
+       [[ "$res" == "$projid" ]] ||
+               error "project id on dirA is $res after enc"
+       res=$($LFS project -d $vaultdir/dirA | awk '{print $2}')
+       [[ "$res" == "P" ]] ||
+               error "project id should have inherit flag (3)"
+}
+run_test 71 "encryption does not remove project flag"
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {