From 957eb359973f03e8c8a59660b4e04f093ed53867 Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Wed, 20 Apr 2022 22:13:13 -0400 Subject: [PATCH] EX-5047 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_104b to verify it. Change-Id: I1be92f365cfe8dea278559b2c34fcee8e42d1c4d Signed-off-by: Qian Yingjin Reviewed-on: https://review.whamcloud.com/47103 Reviewed-by: Feng, Lei Tested-by: jenkins Tested-by: Maloo 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 | 16 +++++++++ lustre/tests/sanity-pcc.sh | 49 ++++++++++++++++++++++++-- lustre/utils/liblustreapi_pcc.c | 8 ++--- 8 files changed, 105 insertions(+), 7 deletions(-) diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 7d3c150..5622870 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -771,6 +771,7 @@ static inline bool lov_pattern_supported_normal_comp(__u32 pattern) #define LOV_V1_INSANE_STRIPE_COUNT 65532 /* maximum stripe count bz13933 */ #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 6081a4b..e73fba3 100644 --- a/lustre/llite/xattr.c +++ b/lustre/llite/xattr.c @@ -400,7 +400,8 @@ int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer, GOTO(out_xattr, rc = -EPERM); if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T && - (type != XATTR_SECURITY_T || strcmp(name, "security.selinux"))) { + (type != XATTR_SECURITY_T || strcmp(name, "security.selinux")) && + (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 30d2c2f7..fd750a5 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -6000,6 +6000,7 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m, m->mdt_enable_dir_auto_split = 0; m->mdt_enable_remote_dir_gid = 0; m->mdt_enable_chprojid_gid = 0; + m->mdt_enable_pin_gid = 0; m->mdt_enable_remote_rename = 1; m->mdt_dir_restripe_nsonly = 1; m->mdt_enable_remote_subdir_mount = 1; diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 0eabbe1..c1844e4 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -303,6 +303,8 @@ struct mdt_device { gid_t mdt_enable_remote_dir_gid; /* user with this gid can change projid */ gid_t mdt_enable_chprojid_gid; + /* 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 441fb02..574b2ff 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -707,6 +707,37 @@ static ssize_t enable_chprojid_gid_store(struct kobject *kobj, } LUSTRE_RW_ATTR(enable_chprojid_gid); +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); + static ssize_t enable_striped_dir_show(struct kobject *kobj, struct attribute *attr, char *buf) { @@ -1414,6 +1445,7 @@ static struct attribute *mdt_attrs[] = { &lustre_attr_enable_remote_dir.attr, &lustre_attr_enable_remote_dir_gid.attr, &lustre_attr_enable_chprojid_gid.attr, + &lustre_attr_enable_pin_gid.attr, &lustre_attr_enable_striped_dir.attr, &lustre_attr_enable_dir_migration.attr, &lustre_attr_enable_dir_restripe.attr, diff --git a/lustre/mdt/mdt_xattr.c b/lustre/mdt/mdt_xattr.c index d1ace5b..97364e0 100644 --- a/lustre/mdt/mdt_xattr.c +++ b/lustre/mdt/mdt_xattr.c @@ -74,6 +74,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); @@ -288,6 +291,9 @@ int mdt_getxattr(struct mdt_thread_info *info) 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); @@ -611,6 +617,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 (!md_capable(uc, 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; } /* Revoke all clients' lookup lock, since the access diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index fefe1a0..1d16c74 100644 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -4497,7 +4497,7 @@ test_203() { } run_test 203 "Verify attach/hit bytes statistics data" -test_204() { +test_204a() { local loopfile="$TMP/$tfile" local mntpt="/mnt/pcc.$tdir" local hsm_root="$mntpt/$tdir" @@ -4564,7 +4564,52 @@ test_204() { do_facet $SINGLEAGT cat $file check_lpcc_state $file "readonly" } -run_test 204 "pin/unpin pcc flag" +run_test 204a "pin/unpin pcc flag" + +test_204d() { + local id="100" + local dir=$DIR/$tdir + local file=$dir/$tfile + local old + + (( $MDS1_VERSION >= $(version_code 2.14.0.38) )) || + skip "Need server version at least 2.14.0.38" + + 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 204d "Permission check for the pin/unpin operation" test_204b() { local loopfile="$TMP/$tfile" diff --git a/lustre/utils/liblustreapi_pcc.c b/lustre/utils/liblustreapi_pcc.c index 1395e5f..2fac644 100644 --- a/lustre/utils/liblustreapi_pcc.c +++ b/lustre/utils/liblustreapi_pcc.c @@ -932,7 +932,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; @@ -1011,7 +1011,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: @@ -1069,9 +1069,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