From: Sebastien Buisson Date: Wed, 5 Jun 2024 12:35:02 +0000 (+0200) Subject: LU-17907 enc: enc flag should not remove other flags X-Git-Tag: 2.15.64~18 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=cfde96fb2e77c33a8ab9afede79cdf093ee8ff9e;p=fs%2Flustre-release.git LU-17907 enc: enc flag should not remove other flags 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 Change-Id: I150f2d87cef112beab81d1d2030133671d4b7361 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55317 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/crypto.c b/lustre/llite/crypto.c index 2a92b07..7c87e08 100644 --- a/lustre/llite/crypto.c +++ b/lustre/llite/crypto.c @@ -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) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 8ca7720..91aa134 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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; diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 4e2e6b1..382ef1a 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index eda4a01..5f380b8 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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 diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 3e61fda..b51b8fa 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -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 */ diff --git a/lustre/tests/sanity-sec.sh b/lustre/tests/sanity-sec.sh index b5d31e8..36e247c 100755 --- a/lustre/tests/sanity-sec.sh +++ b/lustre/tests/sanity-sec.sh @@ -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() {