Whamcloud - gitweb
LU-18919 nodemap: map suppgids from client 59/58759/6
authorSebastien Buisson <sbuisson@ddn.com>
Fri, 11 Apr 2025 13:23:23 +0000 (15:23 +0200)
committerOleg Drokin <green@whamcloud.com>
Fri, 2 May 2025 02:19:20 +0000 (02:19 +0000)
Map back to the file system id space the supplementary groups
received from the client.

Add sanity-sec test_76 to exercise this.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I9d6b6e5ae2fca476b102c8a02a62c1be75379acf
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58759
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Marc Vef <mvef@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/include/lustre_nodemap.h
lustre/mdt/mdt_lib.c
lustre/ptlrpc/nodemap_handler.c
lustre/tests/sanity-sec.sh

index 3f94443..02118a6 100644 (file)
@@ -203,6 +203,7 @@ __u32 nodemap_map_id(struct lu_nodemap *nodemap,
                     enum nodemap_tree_type tree_type, __u32 id);
 ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
                        enum nodemap_tree_type tree_type);
+int nodemap_map_suppgid(struct lu_nodemap *nodemap, int suppgid);
 #ifdef HAVE_SERVER_SUPPORT
 void nodemap_test_nid(struct lnet_nid *nid, char *name_buf, size_t name_len);
 #else
index fafb607..495b04b 100644 (file)
@@ -204,7 +204,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
        __u32 perm = 0;
        int setuid;
        int setgid;
-       int rc = 0;
+       int i, rc = 0;
 
        ENTRY;
        LASSERT(req->rq_auth_gss);
@@ -226,6 +226,9 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                                       NODEMAP_CLIENT_TO_FS, pud->pud_fsuid);
        pud->pud_fsgid = nodemap_map_id(nodemap, NODEMAP_GID,
                                       NODEMAP_CLIENT_TO_FS, pud->pud_fsgid);
+       for (i = 0; i < pud->pud_ngroups; i++)
+               pud->pud_groups[i] = nodemap_map_suppgid(nodemap,
+                                                        pud->pud_groups[i]);
 
        ucred->uc_o_uid = pud->pud_uid;
        ucred->uc_o_gid = pud->pud_gid;
@@ -244,7 +247,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
        if (type == BODY_INIT) {
                struct mdt_body *body = (struct mdt_body *)buf;
 
-               ucred->uc_suppgids[0] = body->mbo_suppgid;
+               ucred->uc_suppgids[0] = nodemap_map_suppgid(nodemap,
+                                                           body->mbo_suppgid);
                ucred->uc_suppgids[1] = -1;
        }
 
@@ -643,7 +647,7 @@ static int old_init_ucred(struct mdt_thread_info *info,
        uc->uc_o_gid = uc->uc_gid = body->mbo_gid;
        uc->uc_o_fsuid = uc->uc_fsuid = body->mbo_fsuid;
        uc->uc_o_fsgid = uc->uc_fsgid = body->mbo_fsgid;
-       uc->uc_suppgids[0] = body->mbo_suppgid;
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, body->mbo_suppgid);
        uc->uc_suppgids[1] = -1;
        uc->uc_ginfo = NULL;
        uc->uc_cap = CAP_EMPTY_SET;
@@ -1245,8 +1249,6 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->sa_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->sa_cap);
-       uc->uc_suppgids[0] = rec->sa_suppgid;
-       uc->uc_suppgids[1] = -1;
 
        rr->rr_fid1 = &rec->sa_fid;
        la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
@@ -1263,6 +1265,8 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
                                    NODEMAP_CLIENT_TO_FS, rec->sa_gid);
        la->la_projid = nodemap_map_id(nodemap, NODEMAP_PROJID,
                                       NODEMAP_CLIENT_TO_FS, rec->sa_projid);
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->sa_suppgid);
+       uc->uc_suppgids[1] = -1;
        nodemap_putref(nodemap);
 
        la->la_size  = rec->sa_size;
@@ -1397,6 +1401,7 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
        struct mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule *pill = info->mti_pill;
        struct md_op_spec *sp = &info->mti_spec;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1410,8 +1415,12 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->cr_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->cr_cap);
-       uc->uc_suppgids[0] = rec->cr_suppgid1;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->cr_suppgid1);
        uc->uc_suppgids[1] = -1;
+       nodemap_putref(nodemap);
        uc->uc_umask = rec->cr_umask;
 
        rr->rr_fid1 = &rec->cr_fid1;
@@ -1502,6 +1511,7 @@ static int mdt_link_unpack(struct mdt_thread_info *info)
        struct lu_attr *attr = &info->mti_attr.ma_attr;
        struct mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule *pill = info->mti_pill;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1515,8 +1525,12 @@ static int mdt_link_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->lk_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->lk_cap);
-       uc->uc_suppgids[0] = rec->lk_suppgid1;
-       uc->uc_suppgids[1] = rec->lk_suppgid2;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->lk_suppgid1);
+       uc->uc_suppgids[1] = nodemap_map_suppgid(nodemap, rec->lk_suppgid2);
+       nodemap_putref(nodemap);
 
        attr->la_uid = rec->lk_fsuid;
        attr->la_gid = rec->lk_fsgid;
@@ -1546,6 +1560,7 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info)
        struct lu_attr *attr = &info->mti_attr.ma_attr;
        struct mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule *pill = info->mti_pill;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1559,8 +1574,12 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->ul_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->ul_cap);
-       uc->uc_suppgids[0] = rec->ul_suppgid1;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->ul_suppgid1);
        uc->uc_suppgids[1] = -1;
+       nodemap_putref(nodemap);
 
        attr->la_uid = rec->ul_fsuid;
        attr->la_gid = rec->ul_fsgid;
@@ -1603,6 +1622,7 @@ static int mdt_rename_unpack(struct mdt_thread_info *info)
        struct mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule *pill = info->mti_pill;
        struct md_op_spec *spec = &info->mti_spec;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1616,8 +1636,12 @@ static int mdt_rename_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->rn_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->rn_cap);
-       uc->uc_suppgids[0] = rec->rn_suppgid1;
-       uc->uc_suppgids[1] = rec->rn_suppgid2;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->rn_suppgid1);
+       uc->uc_suppgids[1] = nodemap_map_suppgid(nodemap, rec->rn_suppgid2);
+       nodemap_putref(nodemap);
 
        attr->la_uid = rec->rn_fsuid;
        attr->la_gid = rec->rn_fsgid;
@@ -1656,6 +1680,7 @@ static int mdt_migrate_unpack(struct mdt_thread_info *info)
        struct mdt_reint_record *rr = &info->mti_rr;
        struct req_capsule *pill = info->mti_pill;
        struct md_op_spec *spec = &info->mti_spec;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1669,8 +1694,12 @@ static int mdt_migrate_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->rn_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->rn_cap);
-       uc->uc_suppgids[0] = rec->rn_suppgid1;
-       uc->uc_suppgids[1] = rec->rn_suppgid2;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->rn_suppgid1);
+       uc->uc_suppgids[1] = nodemap_map_suppgid(nodemap, rec->rn_suppgid2);
+       nodemap_putref(nodemap);
 
        attr->la_uid = rec->rn_fsuid;
        attr->la_gid = rec->rn_fsgid;
@@ -1755,6 +1784,7 @@ static int mdt_open_unpack(struct mdt_thread_info *info)
        struct mdt_reint_record *rr = &info->mti_rr;
        struct ptlrpc_request *req = mdt_info_req(info);
        struct md_op_spec *sp = &info->mti_spec;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1769,8 +1799,12 @@ static int mdt_open_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid = rec->cr_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->cr_cap);
-       uc->uc_suppgids[0] = rec->cr_suppgid1;
-       uc->uc_suppgids[1] = rec->cr_suppgid2;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->cr_suppgid1);
+       uc->uc_suppgids[1] = nodemap_map_suppgid(nodemap, rec->cr_suppgid2);
+       nodemap_putref(nodemap);
        uc->uc_umask = rec->cr_umask;
 
        rr->rr_fid1   = &rec->cr_fid1;
@@ -1844,6 +1878,7 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info)
        struct lu_attr *attr = &info->mti_attr.ma_attr;
        struct req_capsule *pill = info->mti_pill;
        struct mdt_rec_setxattr *rec;
+       struct lu_nodemap *nodemap;
        int rc;
 
        ENTRY;
@@ -1858,8 +1893,12 @@ static int mdt_setxattr_unpack(struct mdt_thread_info *info)
        uc->uc_fsgid  = rec->sx_fsgid;
        uc->uc_cap = CAP_EMPTY_SET;
        ll_set_capability_u32(&uc->uc_cap, rec->sx_cap);
-       uc->uc_suppgids[0] = rec->sx_suppgid1;
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+       uc->uc_suppgids[0] = nodemap_map_suppgid(nodemap, rec->sx_suppgid1);
        uc->uc_suppgids[1] = -1;
+       nodemap_putref(nodemap);
 
        rr->rr_opcode = rec->sx_opcode;
        rr->rr_fid1   = &rec->sx_fid;
index e8a70e5..f6926f2 100644 (file)
@@ -1030,6 +1030,22 @@ ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
 }
 EXPORT_SYMBOL(nodemap_map_acl);
 
+/**
+ * Map supplementary groups received from client.
+ *
+ * \param      lu_nodemap      nodemap
+ * \param      id              id to map
+ *
+ * \retval     mapped id or -1 for invalid suppgid
+ */
+int nodemap_map_suppgid(struct lu_nodemap *nodemap, int suppgid)
+{
+       return suppgid == -1 ? suppgid : nodemap_map_id(nodemap, NODEMAP_GID,
+                                                       NODEMAP_CLIENT_TO_FS,
+                                                       suppgid);
+}
+EXPORT_SYMBOL(nodemap_map_suppgid);
+
 static int nodemap_inherit_properties(struct lu_nodemap *dst,
                                      struct lu_nodemap *src)
 {
index 5885055..f2fdf72 100755 (executable)
@@ -7898,6 +7898,78 @@ test_75() {
 }
 run_test 75 "check uid/gid/projid are set on OST and MDT for various RPCs"
 
+cleanup_76() {
+       # unmount client
+       if is_mounted $MOUNT; then
+               umount_client $MOUNT || error "umount $MOUNT failed"
+       fi
+
+       # reset and deactivate nodemaps, remount client
+       cleanup_local_client_nodemap
+
+       # remount client on $MOUNT_2
+       if [ "$MOUNT_2" ]; then
+               mount_client $MOUNT2 ${MOUNT_OPTS} || error "remount failed"
+       fi
+       wait_ssk
+}
+
+test_76() {
+       local user=$(getent passwd $RUNAS_ID | cut -d: -f1)
+       local grp=grptest76
+       local grpid=5000
+       local nm=c0
+
+       (( $MDS1_VERSION >= $(version_code 2.16.53) )) ||
+               skip "need MDS >= 2.16.53 for suppgroup mapping"
+
+       do_nodes $(comma_list $(all_mdts_nodes)) \
+               $LCTL set_param mdt.*.identity_upcall=NONE
+
+       # create a specific group and add it as a supplementary group for $USER0
+       groupadd -g $grpid $grp
+       stack_trap "groupdel $grp" EXIT
+       usermod -aG $grp $user
+       stack_trap "gpasswd -d $user $grp" EXIT
+
+       stack_trap cleanup_76 EXIT
+
+       # unmount client completely
+       umount_client $MOUNT || error "umount $MOUNT failed"
+       if is_mounted $MOUNT2; then
+               umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+       fi
+
+       # setup nodemap with offset
+       setup_local_client_nodemap $nm 1 1
+       do_facet mgs $LCTL nodemap_add_offset --name $nm \
+               --offset 100000 --limit 200000 ||
+                       error "nodemap_add_offset failed"
+       wait_nm_sync $nm offset
+
+       # remount client to take nodemap into account
+       zconf_mount_clients $HOSTNAME $MOUNT $MOUNT_OPTS ||
+               error "remount failed"
+       wait_ssk
+
+       # Create directory from client part of the nodemap, as root,
+       # and set its group membership to $grpid.
+       # This is going to be mapped on server side.
+       $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+       chgrp -v $grp $DIR/$tdir || error "chgrp $DIR/$tdir failed"
+       chmod -v 0770 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+       ls -ld $DIR/$tdir
+       cancel_lru_locks
+
+       # access as $USER0, should work because it has $grpid as a supp group
+       # and it is properly mapped on server side
+       $RUNAS -G$grpid ls -l $DIR/$tdir ||
+               error "ls -l $DIR/$tdir as $user failed"
+       $RUNAS -G$grpid touch $DIR/$tdir/fileA ||
+               error "touch $DIR/$tdir/fileA as $user failed"
+}
+run_test 76 "suppgroups and gid mapping"
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {