From 54f677651b9a88a72c762f3a30d063db7d5f87c2 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 20 Dec 2023 11:45:50 -0700 Subject: [PATCH] LU-13791 mdt: parameter to tune capabilities Add mdt.*.enable_cap_mask to allow specific capabilities to be enabled and disabled individually. Fixes: f05edf8e2b ("LU-13791 sec: enable FS capabilities") Signed-off-by: Andreas Dilger Change-Id: I6fc0130a90693d673d8c2158e7e31c2de951553d Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53538 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alexander Zarochentsev Reviewed-by: Andrew Perepechko Reviewed-by: Oleg Drokin --- lustre/mdt/mdt_internal.h | 1 + lustre/mdt/mdt_lib.c | 27 +++++++++++++++++++++++++ lustre/mdt/mdt_lproc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ lustre/tests/sanity-sec.sh | 8 ++++++++ 4 files changed, 86 insertions(+) diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 82feadc..22efed4 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -323,6 +323,7 @@ struct mdt_device { gid_t mdt_enable_remote_dir_gid; /* user with this gid can change projid */ gid_t mdt_enable_chprojid_gid; + kernel_cap_t mdt_enable_cap_mask; /* lock for osfs and md_root */ spinlock_t mdt_lock; diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 47a338e..3bb864f 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -349,6 +349,21 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type, /* process root_squash here. */ mdt_root_squash(info, &peernid); + if (ucred->uc_fsuid) { + if (!cap_issubset(ucred->uc_cap, mdt->mdt_enable_cap_mask)) + CDEBUG(D_SEC, "%s: drop capabilities %llx for NID %s\n", + mdt_obd_name(mdt), +#ifdef CAP_FOR_EACH_U32 + ucred->uc_cap.cap[0] | + ((u64)ucred->uc_cap.cap[1] << 32), +#else + ucred->uc_cap.val, +#endif + libcfs_nidstr(&mdt_info_req(info)->rq_peer.nid)); + ucred->uc_cap = cap_intersect(ucred->uc_cap, + mdt->mdt_enable_cap_mask); + } + ucred->uc_valid = UCRED_NEW; ucred_set_jobid(info, ucred); ucred_set_nid(info, ucred); @@ -522,6 +537,18 @@ static int old_init_ucred_common(struct mdt_thread_info *info, mdt_root_squash(info, &mdt_info_req(info)->rq_peer.nid); + if (uc->uc_fsuid) { + if (!cap_issubset(uc->uc_cap, mdt->mdt_enable_cap_mask)) + CDEBUG(D_SEC, "%s: drop capabilities %llx for NID %s\n", + mdt_obd_name(mdt), +#ifdef CAP_FOR_EACH_U32 + uc->uc_cap.cap[0] | ((u64)uc->uc_cap.cap[1]<<32), +#else + uc->uc_cap.val, +#endif + libcfs_nidstr(&mdt_info_req(info)->rq_peer.nid)); + uc->uc_cap = cap_intersect(uc->uc_cap,mdt->mdt_enable_cap_mask); + } uc->uc_valid = UCRED_OLD; ucred_set_jobid(info, uc); ucred_set_nid(info, uc); diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c index 9b13a3b..c6108eb 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -589,6 +589,55 @@ mdt_nosquash_nids_seq_write(struct file *file, const char __user *buffer, } LPROC_SEQ_FOPS(mdt_nosquash_nids); +static ssize_t enable_cap_mask_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); + u64 cap; + + BUILD_BUG_ON(_KERNEL_CAP_T_SIZE != sizeof(u64)); + +#ifdef CAP_FOR_EACH_U32 /* kernels before v6.2-13111-gf122a08b197d */ + cap = ((u64)mdt->mdt_enable_cap_mask.cap[1] << 32) | + mdt->mdt_enable_cap_mask.cap[0]; +#else + cap = mdt->mdt_enable_cap_mask.val; +#endif + return scnprintf(buf, PAGE_SIZE, "%#0llx\n", cap); +} + +static ssize_t enable_cap_mask_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); + unsigned long long val; + int rc; + + rc = kstrtoull(buffer, 0, &val); + if (rc) + /* should also accept symbolic names via cfs_str2mask() */ + return rc; + +#ifdef CAP_FOR_EACH_U32 + mdt->mdt_enable_cap_mask.cap[0] = val & + (CAP_FS_MASK_B0 | CAP_TO_MASK(CAP_SYS_RESOURCE) | + CAP_TO_MASK(CAP_LINUX_IMMUTABLE)); + mdt->mdt_enable_cap_mask.cap[1] = (val >> 32) & CAP_FS_MASK_B1; +#else + mdt->mdt_enable_cap_mask.val = val & + (CAP_FS_MASK | BIT_ULL(CAP_SYS_RESOURCE) | + BIT_ULL(CAP_LINUX_IMMUTABLE)); +#endif + + return count; +} +LUSTRE_RW_ATTR(enable_cap_mask); + static ssize_t enable_remote_dir_gid_show(struct kobject *kobj, struct attribute *attr, char *buf) { @@ -1267,6 +1316,7 @@ static struct attribute *mdt_attrs[] = { &lustre_attr_identity_upcall.attr, &lustre_attr_identity_flush.attr, &lustre_attr_evict_tgt_nids.attr, + &lustre_attr_enable_cap_mask.attr, &lustre_attr_enable_chprojid_gid.attr, &lustre_attr_enable_dir_migration.attr, &lustre_attr_enable_dir_restripe.attr, diff --git a/lustre/tests/sanity-sec.sh b/lustre/tests/sanity-sec.sh index 8de6f43..0d19845 100755 --- a/lustre/tests/sanity-sec.sh +++ b/lustre/tests/sanity-sec.sh @@ -4192,6 +4192,14 @@ test_51() { skip "Need MDS version at least 2.13.53" mkdir $DIR/$tdir || error "mkdir $tdir" + local mdts=$(comma_list $(mdts_nodes)) + local cap_param=mdt.*.enable_cap_mask + + old_cap=($(do_nodes $mdts $LCTL get_param -n $cap_param 2>/dev/null)) + if [[ -n "$old_cap" ]]; then + do_nodes $mdts $LCTL set_param $cap_param=0xf + stack_trap "do_nodes $mdts $LCTL set_param $cap_param=$old_cap" + fi touch $DIR/$tdir/$tfile || error "touch $tfile" cp $(which chown) $DIR/$tdir || error "cp chown" -- 1.8.3.1