From 84100d7f7d38cd7d7c612c190359d27a0554e011 Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Wed, 20 Apr 2022 22:13:13 -0400 Subject: [PATCH] LU-10499 pcc: tunable GID to pin/unpin files In this patch, we adds a tunable "mdt.*.enable_pin_gid" that controls the GID to pin/unpin files. Default should be gid=0, so it is limited to root, gid=-1 so any user can pin/unpin, or gid= to allow a specific GID (e.g. wheel). We add a virtual "lustre.pin" xattr to set/get the xattr for non-root users, if mdt.*.enable_pin_gid is set correctly. Add test case sanity-pcc test_204b to verify it. EX-bug-id: EX-5047 Change-Id: I1be92f365cfe8dea278559b2c34fcee8e42d1c4d Signed-off-by: Qian Yingjin Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54463 Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Reviewed-by: Feng Lei Reviewed-by: Andreas Dilger --- lustre/include/uapi/linux/lustre/lustre_user.h | 1 + lustre/llite/xattr.c | 3 +- lustre/mdt/mdt_handler.c | 1 + lustre/mdt/mdt_internal.h | 2 ++ lustre/mdt/mdt_lproc.c | 32 +++++++++++++++++ lustre/mdt/mdt_xattr.c | 17 +++++++++ lustre/tests/sanity-pcc.sh | 50 +++++++++++++++++++++++++- lustre/utils/liblustreapi_pcc.c | 8 ++--- 8 files changed, 108 insertions(+), 6 deletions(-) diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 42fc4ab..1095a08 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -821,6 +821,7 @@ static inline bool lov_pool_is_reserved(const char *pool) #define LOV_V1_INSANE_STRIPE_COUNT LOV_V1_INSANE_STRIPE_INDEX /* deprecated */ #define XATTR_LUSTRE_PREFIX "lustre." +#define XATTR_LUSTRE_PIN XATTR_LUSTRE_PREFIX"pin" #define XATTR_LUSTRE_LOV XATTR_LUSTRE_PREFIX"lov" /* Please update if XATTR_LUSTRE_LOV".set" groks more flags in the future */ diff --git a/lustre/llite/xattr.c b/lustre/llite/xattr.c index fdf3ad9..e5c9216 100644 --- a/lustre/llite/xattr.c +++ b/lustre/llite/xattr.c @@ -474,7 +474,8 @@ int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T && (type != XATTR_SECURITY_T || !ll_xattr_is_seclabel(name)) && - (type != XATTR_TRUSTED_T || strcmp(name, XATTR_NAME_SOM))) { + (type != XATTR_TRUSTED_T || strcmp(name, XATTR_NAME_SOM)) && + (type != XATTR_LUSTRE_T || strcmp(name, XATTR_LUSTRE_PIN))) { rc = ll_xattr_cache_get(inode, name, buffer, size, valid); if (rc == -EAGAIN) goto getxattr_nocache; diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 25f27e8..5103049 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -6435,6 +6435,7 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m, m->mdt_enable_parallel_rename_crossdir = 1; m->mdt_enable_remote_dir = 1; m->mdt_enable_remote_dir_gid = 0; + m->mdt_enable_pin_gid = 0; m->mdt_enable_remote_rename = 1; m->mdt_enable_striped_dir = 1; m->mdt_enable_dmv_implicit_inherit = 1; diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index e76ce9e..96511cb 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -327,6 +327,8 @@ struct mdt_device { /* user with this gid can change projid */ gid_t mdt_enable_chprojid_gid; kernel_cap_t mdt_enable_cap_mask; + /* user with this gid can pin/unpin file */ + gid_t mdt_enable_pin_gid; /* lock for osfs and md_root */ spinlock_t mdt_lock; diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c index 21f5ed2..775afbc 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -867,6 +867,37 @@ MDT_BOOL_RW_ATTR(enable_strict_som); MDT_BOOL_RW_ATTR(enable_dmv_implicit_inherit); MDT_BOOL_RW_ATTR(enable_dmv_xattr); +static ssize_t enable_pin_gid_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct obd_device *obd = container_of(kobj, struct obd_device, + obd_kset.kobj); + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + + if (mdt->mdt_enable_pin_gid == ~0U) + return scnprintf(buf, PAGE_SIZE, "-1\n"); + return scnprintf(buf, PAGE_SIZE, "%u\n", mdt->mdt_enable_pin_gid); +} + +static ssize_t enable_pin_gid_store(struct kobject *kobj, + struct attribute *attr, + const char *buffer, size_t count) +{ + struct obd_device *obd = container_of(kobj, struct obd_device, + obd_kset.kobj); + struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); + int val; + int rc; + + rc = kstrtoint(buffer, 0, &val); + if (rc) + return rc; + + mdt->mdt_enable_pin_gid = val; + return count; +} +LUSTRE_RW_ATTR(enable_pin_gid); + /** * Show if the MDT is in no create mode. * @@ -1452,6 +1483,7 @@ static struct attribute *mdt_attrs[] = { &lustre_attr_evict_tgt_nids.attr, &lustre_attr_enable_cap_mask.attr, &lustre_attr_enable_chprojid_gid.attr, + &lustre_attr_enable_pin_gid.attr, &lustre_attr_enable_dir_migration.attr, &lustre_attr_enable_dir_restripe.attr, &lustre_attr_enable_dir_auto_split.attr, diff --git a/lustre/mdt/mdt_xattr.c b/lustre/mdt/mdt_xattr.c index f2f1c47..7fc93bd 100644 --- a/lustre/mdt/mdt_xattr.c +++ b/lustre/mdt/mdt_xattr.c @@ -73,6 +73,9 @@ static int mdt_getxattr_pack_reply(struct mdt_thread_info *info) !strncmp(xattr_name, user_string, sizeof(user_string) - 1)) RETURN(-EOPNOTSUPP); + if (strcmp(xattr_name, XATTR_LUSTRE_PIN) == 0) + xattr_name = XATTR_NAME_PIN; + size = mo_xattr_get(info->mti_env, mdt_object_child(info->mti_object), &LU_BUF_NULL, xattr_name); @@ -286,6 +289,10 @@ int mdt_getxattr(struct mdt_thread_info *info) if (valid == OBD_MD_FLXATTR) { const char *xattr_name = req_capsule_client_get(info->mti_pill, &RMF_NAME); + + if (strcmp(xattr_name, XATTR_LUSTRE_PIN) == 0) + xattr_name = XATTR_NAME_PIN; + rc = mo_xattr_get(info->mti_env, next, buf, xattr_name); if (rc < 0) GOTO(out, rc); @@ -602,6 +609,16 @@ int mdt_reint_setxattr(struct mdt_thread_info *info, } lockpart |= MDS_INODELOCK_LAYOUT; + } else if ((strcmp(xattr_name, XATTR_LUSTRE_PIN) == 0)) { + struct mdt_device *mdt = info->mti_mdt; + struct lu_ucred *uc = mdt_ucred(info); + + if (!cap_raised(uc->uc_cap, CAP_SYS_RESOURCE) && + !lustre_in_group_p(uc, mdt->mdt_enable_pin_gid) && + !(mdt->mdt_enable_pin_gid == -1)) + GOTO(out, rc = -EPERM); + + xattr_name = XATTR_NAME_PIN; } if (!strcmp(xattr_name, XATTR_NAME_ACL_ACCESS)) diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index 9f2cb6c..f09bd20 100755 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -4692,6 +4692,54 @@ test_204a() { run_test 204a "pin/unpin pcc flag" test_204b() { + local id="100" + local dir=$DIR/$tdir + local file=$dir/$tfile + local old + + $LCTL get_param -n mdc.*.connect_flags | grep -q pcc_ro || + skip "Server does not support PCC-RO" + + (( $MDS1_VERSION >= $(version_code 2.15.61) )) || + skip "Need server version at least 2.15.61" + + old=$(do_facet mds1 $LCTL get_param -n mdt.*.enable_pin_gid | head -1) + do_facet mds1 $LCTL set_param mdt.*.enable_pin_gid=0 + stack_trap "do_facet mds1 $LCTL set_param mdt.*.enable_pin_gid=$old" + + mkdir_on_mdt0 -p $dir || error "mkdir $dir failed" + chmod 777 $dir || error "chown $dir failed" + $RUNAS touch $file || error "touch $file failed" + $RUNAS $LFS pcc pin -i $id $file && + error "normal user should not able to pin any file" + $LFS pcc pin -i $id $file || error "root should be able to pin any file" + getfattr -d -n trusted.pin $file + $RUNAS $LFS pcc unpin -i $id $file && + error "nonroot user should fail to unpin file" + $LFS pcc unpin -i $id $file || + error "root should be able to unpin any file" + $RUNAS $LFS pcc pin -i $id $file && + error "nonroot user should fail to pin file" + + do_facet mds1 $LCTL set_param mdt.*.enable_pin_gid=-1 + $RUNAS $LFS pcc pin -i $id $file || + error "failed to pin $file when enable_pin_gid=-1" + $RUNAS $LFS pcc unpin -i $id $file || + error "failed to unpin $file when enable_pin_gid=-1" + + do_facet mds1 $LCTL set_param mdt.*.enable_pin_gid=$RUNAS_GID + $RUNAS $LFS pcc pin -i $id $file || + error "failed to pin $file when enable_pin_gid=$RUNAS_GID" + $RUNAS $LFS pcc unpin -i $id $file || + error "failed to unpin $file when enable_pin_gid=$RUNAS_GID" + $LFS pcc pin -i $id $file || + error "failed to pin $file when enable_pin_gid=$RUNAS_GID" + $LFS pcc unpin -i $id $file || + error "failed to unpin $file when enable_pin_gid=$RUNAS_GID" +} +run_test 204b "Permission check for the pin/unpin operation" + +test_204c() { local loopfile="$TMP/$tfile" local mntpt="/mnt/pcc.$tdir" local hsm_root="$mntpt/$tdir" @@ -4727,7 +4775,7 @@ test_204b() { xattrvalue=$(do_facet $SINGLEAGT getfattr $file -n $xattrname --only-values) [[ -z "$xattrvalue" ]] || error "incorrect xattr $xattrname=$xattrvalue" } -run_test 204b "PCC pin/unpin without attach ID specified" +run_test 204c "PCC pin/unpin without attach ID specified" complete_test $SECONDS check_and_cleanup_lustre diff --git a/lustre/utils/liblustreapi_pcc.c b/lustre/utils/liblustreapi_pcc.c index 0e4f48f..2c4bcbd 100644 --- a/lustre/utils/liblustreapi_pcc.c +++ b/lustre/utils/liblustreapi_pcc.c @@ -927,7 +927,7 @@ static struct cYAML *read_pin_xattr_object(const char *path) struct cYAML *yaml = NULL; char buff[XATTR_SIZE_MAX]; - rc = getxattr(path, XATTR_NAME_PIN, buff, sizeof(buff)); + rc = getxattr(path, XATTR_LUSTRE_PIN, buff, sizeof(buff)); if (rc < 0) goto out; @@ -1006,7 +1006,7 @@ int llapi_pcc_pin_file(const char *path, __u32 id) goto out; set: - rc = setxattr(path, XATTR_NAME_PIN, buff, strlen(buff), 0); + rc = setxattr(path, XATTR_LUSTRE_PIN, buff, strlen(buff), 0); if (rc < 0) rc = -errno; out: @@ -1064,9 +1064,9 @@ int llapi_pcc_unpin_file(const char *path, __u32 id) goto out; if (strlen(buff) == 0) - rc = removexattr(path, XATTR_NAME_PIN); + rc = removexattr(path, XATTR_LUSTRE_PIN); else - rc = setxattr(path, XATTR_NAME_PIN, buff, strlen(buff), 0); + rc = setxattr(path, XATTR_LUSTRE_PIN, buff, strlen(buff), 0); if (rc < 0) rc = -errno; -- 1.8.3.1