-void mds_body_do_reverse_map(struct mds_export_data *med,
- struct mds_body *body)
-{
- uid_t uid;
- gid_t gid;
-
- if (!med->med_remote)
- return;
-
- ENTRY;
- if (body->valid & OBD_MD_FLUID) {
- uid = mds_idmap_lookup_uid(med->med_idmap, 1, body->uid);
- if (uid == MDS_IDMAP_NOTFOUND) {
- uid = med->med_nllu;
- if (body->valid & OBD_MD_FLMODE) {
- body->mode = (body->mode & ~S_IRWXU) |
- ((body->mode & S_IRWXO) << 6);
- }
- }
- body->uid = uid;
- }
- if (body->valid & OBD_MD_FLGID) {
- gid = mds_idmap_lookup_gid(med->med_idmap, 1, body->gid);
- if (gid == MDS_IDMAP_NOTFOUND) {
- gid = med->med_nllg;
- if (body->valid & OBD_MD_FLMODE) {
- body->mode = (body->mode & ~S_IRWXG) |
- ((body->mode & S_IRWXO) << 3);
- }
- }
- body->gid = gid;
- }
-
- EXIT;
-}
-
-/**********************
- * MDS ucred handling *
- **********************/
-
-static inline void drop_ucred_ginfo(struct lvfs_ucred *ucred)
-{
- if (ucred->luc_ginfo) {
- put_group_info(ucred->luc_ginfo);
- ucred->luc_ginfo = NULL;
- }
-}
-
-static inline void drop_ucred_lsd(struct lvfs_ucred *ucred)
-{
- if (ucred->luc_lsd) {
- mds_put_lsd(ucred->luc_lsd);
- ucred->luc_lsd = NULL;
- }
-}
-
-/*
- * the heart of the uid/gid handling and security checking.
- *
- * root could set any group_info if we allowed setgroups, while
- * normal user only could 'reduce' their group members -- which
- * is somewhat expensive.
- *
- * authenticated as mds user (using mds service credential) could
- * bypass all checkings.
- */
-int mds_init_ucred(struct lvfs_ucred *ucred,
- struct ptlrpc_request *req,
- struct mds_req_sec_desc *rsd)
-{
- struct mds_obd *mds = &req->rq_export->exp_obd->u.mds;
- struct mds_export_data *med = &req->rq_export->u.eu_mds_data;
- struct lustre_sec_desc *lsd;
- ptl_nid_t peernid = req->rq_peer.peer_id.nid;
- struct group_info *gnew;
- unsigned int setuid, setgid, strong_sec, root_squashed;
- __u32 lsd_perms;
- ENTRY;
-
- LASSERT(ucred);
- LASSERT(rsd);
- LASSERT(rsd->rsd_ngroups <= LUSTRE_MAX_GROUPS);
-
- if (SEC_FLAVOR_MAJOR(req->rq_req_secflvr) == PTLRPCS_FLVR_MAJOR_GSS &&
- (SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_AUTH ||
- SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV))
- strong_sec = 1;
- else
- strong_sec = 0;
-
- LASSERT(!(req->rq_remote_realm && !strong_sec));
-
- if (strong_sec && req->rq_auth_uid == -1) {
- CWARN("user not authenticated, deny access\n");
- RETURN(-EPERM);
- }
-
- /* sanity check: if we use strong authentication, we expect the
- * uid which client claimed is true.
- * not apply to special mds user .
- */
- if (!req->rq_auth_usr_mds && strong_sec) {
- if (!med->med_remote) {
- if (req->rq_auth_uid != rsd->rsd_uid) {
- CERROR("local client "LPU64": auth uid %u "
- "while client claim %u:%u/%u:%u\n",
- peernid, req->rq_auth_uid,
- rsd->rsd_uid, rsd->rsd_gid,
- rsd->rsd_fsuid, rsd->rsd_fsgid);
- RETURN(-EPERM);
- }
- } else {
- if (req->rq_mapped_uid == MDS_IDMAP_NOTFOUND) {
- CWARN("no mapping found, deny\n");
- RETURN(-EPERM);
- }
-
- if (mds_req_secdesc_do_map(med, rsd))
- RETURN(-EPERM);
-
- if (req->rq_mapped_uid != rsd->rsd_uid) {
- CERROR("remote client "LPU64": auth uid %u "
- "while client claim %u:%u/%u:%u\n",
- peernid, req->rq_auth_uid,
- rsd->rsd_uid, rsd->rsd_gid,
- rsd->rsd_fsuid, rsd->rsd_fsgid);
- RETURN(-EPERM);
- }
- }
- }
-
- /* now LSD come into play */
- ucred->luc_ginfo = NULL;
- ucred->luc_lsd = lsd = mds_get_lsd(rsd->rsd_uid);
-
- if (!lsd) {
- CERROR("Deny access without LSD: uid %d\n", rsd->rsd_uid);
- RETURN(-EPERM);
- }
-
- lsd_perms = mds_lsd_get_perms(lsd, med->med_remote, 0, peernid);
-
- /* check setuid/setgid permissions.
- * again not apply to special mds user.
- */
- if (!req->rq_auth_usr_mds) {
- /* find out the setuid/setgid attempt */
- setuid = (rsd->rsd_uid != rsd->rsd_fsuid);
- setgid = (rsd->rsd_gid != rsd->rsd_fsgid ||
- rsd->rsd_gid != lsd->lsd_gid);
-
- /* check permission of setuid */
- if (setuid && !(lsd_perms & LSD_PERM_SETUID)) {
- CWARN("mds blocked setuid attempt (%u -> %u) "
- "from "LPU64"\n", rsd->rsd_uid, rsd->rsd_fsuid,
- peernid);
- RETURN(-EPERM);
- }
-
- /* check permission of setgid */
- if (setgid && !(lsd_perms & LSD_PERM_SETGID)) {
- CWARN("mds blocked setgid attempt (%u:%u/%u:%u -> %u) "
- "from "LPU64"\n", rsd->rsd_uid, rsd->rsd_gid,
- rsd->rsd_fsuid, rsd->rsd_fsgid, lsd->lsd_gid,
- peernid);
- RETURN(-EPERM);
- }
- }
-
- root_squashed = mds_squash_root(mds, rsd, &peernid);
-
- /* remove privilege for non-root user */
- if (rsd->rsd_fsuid)
- rsd->rsd_cap &= ~CAP_FS_MASK;
-
- /* by now every fields other than groups in rsd have been granted */
- ucred->luc_uid = rsd->rsd_uid;
- ucred->luc_gid = rsd->rsd_gid;
- ucred->luc_fsuid = rsd->rsd_fsuid;
- ucred->luc_fsgid = rsd->rsd_fsgid;
- ucred->luc_cap = rsd->rsd_cap;
-
- /* don't use any supplementary group if we squashed root.
- * XXX The exact behavior of root_squash is not defined, we just
- * keep the reminder here */
- if (root_squashed)
- RETURN(0);
-
- /* install groups from LSD */
- if (lsd->lsd_ginfo) {
- ucred->luc_ginfo = lsd->lsd_ginfo;
- get_group_info(ucred->luc_ginfo);
- }
-
- /* everything is done if we don't allow setgroups, or it is
- * from remote client (which implies forced to be no-setgroups).
- *
- * Note: remote user's supplementary groups sent along the request
- * (if any) are all ignored, but we make the mapped local user's
- * supplementary groups take effect.
- */
- if (med->med_remote || !(lsd_perms & LSD_PERM_SETGRP))
- RETURN(0);
-
- /* root could set any groups as he want (if allowed), normal
- * users only could reduce his group array.
- */
- if (ucred->luc_uid == 0) {
- drop_ucred_ginfo(ucred);
-
- if (rsd->rsd_ngroups == 0)
- RETURN(0);
-
- gnew = groups_alloc(rsd->rsd_ngroups);
- if (!gnew) {
- CERROR("out of memory\n");
- drop_ucred_lsd(ucred);
- RETURN(-ENOMEM);
- }
- groups_from_buffer(gnew, rsd->rsd_groups);
- groups_sort(gnew); /* don't rely on client doing this */
-
- ucred->luc_ginfo = gnew;
- } else {
- __u32 set = 0, cur = 0;
- struct group_info *ginfo = ucred->luc_ginfo;
-
- if (!ginfo)
- RETURN(0);
-
- /* Note: freeing a group_info count on 'nblocks' instead of
- * 'ngroups', thus we can safely alloc enough buffer and reduce
- * and ngroups number later.
- */
- gnew = groups_alloc(rsd->rsd_ngroups);
- if (!gnew) {
- CERROR("out of memory\n");
- drop_ucred_ginfo(ucred);
- drop_ucred_lsd(ucred);
- RETURN(-ENOMEM);
- }
-
- while (cur < rsd->rsd_ngroups) {
- if (groups_search(ginfo, rsd->rsd_groups[cur])) {
- GROUP_AT(gnew, set) = rsd->rsd_groups[cur];
- set++;
- }
- cur++;
- }
- gnew->ngroups = set;
-
- put_group_info(ucred->luc_ginfo);
- ucred->luc_ginfo = gnew;
- }
- RETURN(0);
-}
-
-void mds_exit_ucred(struct lvfs_ucred *ucred)