/* check permission of setgid */
if (setgid && !(perm & CFS_SETGID_PERM)) {
- CDEBUG(D_SEC, "mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
- "from %s\n", pud->pud_uid, pud->pud_gid,
+ CDEBUG(D_SEC,
+ "mdt blocked setgid attempt (%u:%u/%u:%u -> %d) from %s\n",
+ pud->pud_uid, pud->pud_gid,
pud->pud_fsuid, pud->pud_fsgid,
- ucred->uc_identity->mi_gid, libcfs_nidstr(&peernid));
+ ucred->uc_identity ? ucred->uc_identity->mi_gid : -1,
+ libcfs_nidstr(&peernid));
GOTO(out, rc = -EACCES);
}
mdt->mdt_enable_cap_mask);
}
+ /* Thanks to Kerberos, Lustre does not have to trust clients anymore,
+ * but relies on keytabs and tickets, cryptographically validated, to
+ * recognize clients and users.
+ * RPC provided primary group should match the one got from the
+ * identity upcall.
+ * And RPC provided supplementary groups should not be trusted,
+ * but checked thanks to identity upcall and the trusted UID
+ * from the ticket.
+ */
+ if (SPTLRPC_FLVR_MECH(req->rq_flvr.sf_rpc) == SPTLRPC_MECH_GSS_KRB5) {
+ if (!has_proper_groups(ucred))
+ GOTO(out, rc = -EACCES);
+ ucred->uc_suppgids[0] = -1;
+ ucred->uc_suppgids[1] = -1;
+ if (ucred->uc_ginfo) {
+ put_group_info(ucred->uc_ginfo);
+ ucred->uc_ginfo = NULL;
+ }
+ }
+
ucred->uc_valid = UCRED_NEW;
ucred_set_jobid(info, ucred);
ucred_set_nid(info, ucred);
static int old_init_ucred_common(struct mdt_thread_info *info,
struct lu_nodemap *nodemap)
{
- struct lu_ucred *uc = mdt_ucred(info);
- struct mdt_device *mdt = info->mti_mdt;
- struct md_identity *identity = NULL;
+ struct ptlrpc_request *req = mdt_info_req(info);
+ struct lu_ucred *uc = mdt_ucred(info);
+ struct mdt_device *mdt = info->mti_mdt;
+ struct md_identity *identity = NULL;
if (nodemap && uc->uc_o_uid == nodemap->nm_squash_uid
&& nodemap->nmf_deny_unknown)
libcfs_nidstr(&mdt_info_req(info)->rq_peer.nid));
uc->uc_cap = cap_intersect(uc->uc_cap,mdt->mdt_enable_cap_mask);
}
+
+ /* Thanks to Kerberos, Lustre does not have to trust clients anymore,
+ * but relies on keytabs and tickets, cryptographically validated, to
+ * recognize clients and users.
+ * RPC provided primary group should match the one got from the
+ * identity upcall.
+ * And RPC provided supplementary groups should not be trusted,
+ * but checked thanks to identity upcall and the trusted UID
+ * from the ticket.
+ */
+ if (SPTLRPC_FLVR_MECH(req->rq_flvr.sf_rpc) == SPTLRPC_MECH_GSS_KRB5) {
+ if (!has_proper_groups(uc)) {
+ mdt_identity_put(mdt->mdt_identity_cache,
+ uc->uc_identity);
+ uc->uc_identity = NULL;
+ RETURN(-EACCES);
+ }
+ uc->uc_suppgids[0] = -1;
+ uc->uc_suppgids[1] = -1;
+ }
+
uc->uc_valid = UCRED_OLD;
ucred_set_jobid(info, uc);
ucred_set_nid(info, uc);
ucred_set_rbac_roles(info, uc);
EXIT;
-
return 0;
}
* groups_search() is copied from linux kernel!
* A simple bsearch.
*/
-static int lustre_groups_search(struct group_info *group_info,
- gid_t grp)
+int lustre_groups_search(struct group_info *group_info, gid_t grp)
{
int left, right;
}
return 0;
}
+EXPORT_SYMBOL(lustre_groups_search);
void lustre_groups_from_list(struct group_info *ginfo, gid_t *glist)
{
return rc;
}
EXPORT_SYMBOL(lustre_in_group_p);
+
+/* make sure fsgid is one of primary or supplementary groups
+ * fetched from identity upcall
+ */
+int has_proper_groups(struct lu_ucred *ucred)
+{
+ struct group_info *group_info = NULL;
+ int rc;
+
+ if (!ucred->uc_identity)
+ return 1;
+
+ if (ucred->uc_fsgid == ucred->uc_identity->mi_gid)
+ return 1;
+
+ group_info = ucred->uc_identity->mi_ginfo;
+ if (!group_info)
+ return 0;
+
+ get_group_info(group_info);
+ rc = lustre_groups_search(group_info, ucred->uc_fsgid);
+ put_group_info(group_info);
+
+ return rc;
+}
+EXPORT_SYMBOL(has_proper_groups);
}
run_test 8 "Early reply sent for slow gss context negotiation"
+test_9() {
+ local test9user=$(getent passwd $RUNAS_ID | cut -d: -f1)
+
+ $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ chmod 0777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+ $RUNAS ls -ld $DIR/$tdir
+
+ # Add group, and client to new group, on client only.
+ # Server is not aware.
+ groupadd -g 5000 grptest9
+ stack_trap "groupdel grptest9" EXIT
+
+ usermod -g grptest9 $test9user
+ stack_trap "usermod -g $test9user $test9user" EXIT
+ id $RUNAS_ID
+ # Thanks to Kerberos, client should not be able to create file
+ # with primary group not known on server side
+ $RUNAS touch $DIR/$tdir/fileA &&
+ error "server should not trust client's primary gid"
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+
+ do_facet mds1 groupadd -g 5000 grptest9
+ stack_trap "do_facet mds1 groupdel grptest9 || true" EXIT
+ do_facet mds1 usermod -a -G grptest9 $test9user
+ stack_trap "do_facet mds1 gpasswd -d $test9user grptest9 || true" EXIT
+ id $RUNAS_ID
+ do_facet mds1 "id $RUNAS_ID"
+ # Thanks to Kerberos, client should be able to create file
+ # with primary group taken as one of supp groups, as long as
+ # server side knows the supp groups.
+ $RUNAS touch $DIR/$tdir/fileA ||
+ error "server should know client's supp gid"
+ ls -l $DIR/$tdir
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+ do_facet mds1 gpasswd -d $test9user grptest9
+ do_facet mds1 groupdel grptest9
+ usermod -g $test9user $test9user
+
+ usermod -a -G grptest9 $test9user
+ stack_trap "gpasswd -d $test9user grptest9" EXIT
+ id $RUNAS_ID
+ $RUNAS touch $DIR/$tdir/fileB
+ ls -l $DIR/$tdir
+ # Thanks to Kerberos, client should not be able to chgrp
+ $RUNAS chgrp grptest9 $DIR/$tdir/fileB &&
+ error "server should not trust client's supp gid"
+ ls -l $DIR/$tdir
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+}
+run_test 9 "Do not trust primary and supp gids from client"
+
#
# following tests will manipulate flavors and may end with any flavor set,
# so each test should not assume any start flavor.