Whamcloud - gitweb
Transmit group_info between mds.
authorfanyong <fanyong>
Wed, 27 Sep 2006 05:17:29 +0000 (05:17 +0000)
committerfanyong <fanyong>
Wed, 27 Sep 2006 05:17:29 +0000 (05:17 +0000)
lustre/cmm/mdc_object.c
lustre/include/md_object.h
lustre/mdd/mdd_handler.c
lustre/mdt/mdt_identity.c
lustre/mdt/mdt_idmap.c
lustre/mdt/mdt_lib.c

index b1f45da..a26370a 100644 (file)
@@ -258,10 +258,15 @@ static int mdc_object_create(const struct lu_context *ctx,
                 uid = uc->mu_fsuid;
                 gid = uc->mu_fsgid;
                 cap = uc->mu_cap;
+                if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
+                        mci->mci_opdata.suppgids[0] = uc->mu_suppgids[0];
+                else
+                        mci->mci_opdata.suppgids[0] = -1;
         } else {
                 uid = la->la_uid;
                 gid = la->la_gid;
                 cap = 0;
+                mci->mci_opdata.suppgids[0] = -1;
         }
 
         /* get data from spec */
@@ -312,10 +317,18 @@ static int mdc_ref_add(const struct lu_context *ctx, struct md_object *mo,
                 mci->mci_opdata.fsuid = uc->mu_fsuid;
                 mci->mci_opdata.fsgid = uc->mu_fsgid;
                 mci->mci_opdata.cap = uc->mu_cap;
+                if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
+                        mci->mci_opdata.suppgids[0] = uc->mu_suppgids[0];
+                        mci->mci_opdata.suppgids[1] = uc->mu_suppgids[1];
+                } else {
+                        mci->mci_opdata.suppgids[0] =
+                                mci->mci_opdata.suppgids[1] = -1;
+                }
         } else {
                 mci->mci_opdata.fsuid = current->fsuid;
                 mci->mci_opdata.fsgid = current->fsgid;
                 mci->mci_opdata.cap = current->cap_effective;
+                mci->mci_opdata.suppgids[0] = mci->mci_opdata.suppgids[1] = -1;
         }
 
 
@@ -344,10 +357,15 @@ static int mdc_ref_del(const struct lu_context *ctx, struct md_object *mo,
                 mci->mci_opdata.fsuid = uc->mu_fsuid;
                 mci->mci_opdata.fsgid = uc->mu_fsgid;
                 mci->mci_opdata.cap = uc->mu_cap;
+                if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
+                        mci->mci_opdata.suppgids[0] = uc->mu_suppgids[0];
+                else
+                        mci->mci_opdata.suppgids[0] = -1;
         } else {
                 mci->mci_opdata.fsuid = la->la_uid;
                 mci->mci_opdata.fsgid = la->la_gid;
                 mci->mci_opdata.cap = current->cap_effective;
+                mci->mci_opdata.suppgids[0] = -1;
         }
 
         rc = md_unlink(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
@@ -407,10 +425,18 @@ static int mdc_rename_tgt(const struct lu_context *ctx, struct md_object *mo_p,
                 mci->mci_opdata.fsuid = uc->mu_fsuid;
                 mci->mci_opdata.fsgid = uc->mu_fsgid;
                 mci->mci_opdata.cap = uc->mu_cap;
+                if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
+                        mci->mci_opdata.suppgids[0] = uc->mu_suppgids[0];
+                        mci->mci_opdata.suppgids[1] = uc->mu_suppgids[1];
+                } else {
+                        mci->mci_opdata.suppgids[0] =
+                                mci->mci_opdata.suppgids[1] = -1;
+                }
         } else {
                 mci->mci_opdata.fsuid = la->la_uid;
                 mci->mci_opdata.fsgid = la->la_gid;
                 mci->mci_opdata.cap = current->cap_effective;
+                mci->mci_opdata.suppgids[0] = mci->mci_opdata.suppgids[1] = -1;
         }
 
         rc = md_rename(mc->mc_desc.cl_exp, &mci->mci_opdata, NULL, 0,
index d049892..403f2f2 100644 (file)
@@ -64,6 +64,7 @@ struct md_ucred {
         __u32                   mu_gid;
         __u32                   mu_fsuid;
         __u32                   mu_fsgid;
+        __u32                   mu_suppgids[2];
         __u32                   mu_cap;
         __u32                   mu_umask;
        struct group_info      *mu_ginfo;
index 2e4ca88..1204385 100644 (file)
@@ -183,6 +183,11 @@ static int mdd_in_group_p(struct md_ucred *uc, gid_t grp)
         if (grp != uc->mu_fsgid) {
                 struct group_info *group_info = NULL;
 
+                if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
+                        if ((grp == uc->mu_suppgids[0]) ||
+                            (grp == uc->mu_suppgids[1]))
+                                return 1;
+
                 if (uc->mu_ginfo)
                         group_info = uc->mu_ginfo;
                 else if (uc->mu_identity)
index 17f78b8..805b9db 100644 (file)
@@ -171,27 +171,10 @@ struct mdt_identity *mdt_identity_get(struct upcall_cache *cache, __u32 uid)
 {
         struct upcall_cache_entry *entry;
 
-        entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
-        if (IS_ERR(entry)) {
-                CERROR("upcall_cache_get_entry failed: %ld\n", PTR_ERR(entry));
+        if (!cache)
                 return NULL;
-        }
 
-        return &entry->u.identity;
-}
-
-#if 0
-struct mdt_identity *mdt_identity_get(struct mdt_thread_info *info,
-                                      struct upcall_cache *cache, __u32 uid)
-{
-        struct ptlrpc_request *req = mdt_info_req(info);
-        struct lvfs_run_ctxt saved;
-        struct obd_device *obd = req->rq_export->exp_obd;
-        struct upcall_cache_entry *entry;
-
-        push_ctxt(&saved, &obd->obd_lvfs_ctxt, &info->mti_uc);
         entry = upcall_cache_get_entry(cache, (__u64)uid, NULL);
-        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &info->mti_uc);
         if (IS_ERR(entry)) {
                 CERROR("upcall_cache_get_entry failed: %ld\n", PTR_ERR(entry));
                 return NULL;
@@ -199,10 +182,12 @@ struct mdt_identity *mdt_identity_get(struct mdt_thread_info *info,
 
         return &entry->u.identity;
 }
-#endif
 
 void mdt_identity_put(struct upcall_cache *cache, struct mdt_identity *identity)
 {
+        if (!cache)
+                return;
+
         LASSERT(identity);
         upcall_cache_put_entry(cache, identity->mi_uc_entry);
 }
@@ -255,53 +240,21 @@ int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
         if (!med->med_rmtclient)
                 RETURN(-EBADE);
 
+        if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
+                RETURN(-EINVAL);
+
         perm->rp_uid = uc->mu_o_uid;
         perm->rp_gid = uc->mu_o_gid;
         perm->rp_fsuid = uc->mu_o_fsuid;
         perm->rp_fsgid = uc->mu_o_fsgid;
 
         perm->rp_access_perm = 0;
-        if (mo_permission(info->mti_ctxt, next, MAY_READ, &info->mti_uc) == 0)
+        if (mo_permission(info->mti_ctxt, next, MAY_READ, uc) == 0)
                 perm->rp_access_perm |= MAY_READ;
-        if (mo_permission(info->mti_ctxt, next, MAY_WRITE, &info->mti_uc) == 0)
+        if (mo_permission(info->mti_ctxt, next, MAY_WRITE, uc) == 0)
                 perm->rp_access_perm |= MAY_WRITE;
-        if (mo_permission(info->mti_ctxt, next, MAY_EXEC, &info->mti_uc) == 0)
+        if (mo_permission(info->mti_ctxt, next, MAY_EXEC, uc) == 0)
                 perm->rp_access_perm |= MAY_EXEC;
 
         RETURN(0);
 }
-
-#if 0
-int mdt_pack_remote_perm(struct mdt_thread_info *info, struct mdt_object *o,
-                         void *buf)
-{
-        struct ptlrpc_request   *req = mdt_info_req(info);
-        struct lvfs_ucred       *uc = &info->mti_uc;
-        struct md_object        *next = mdt_object_child(o);
-        struct mdt_export_data  *med = mdt_req2med(req);
-        struct ptlrpc_user_desc *pud = req->rq_user_desc;
-        struct mdt_remote_perm  *perm = buf;
-        int                     rc;
-        ENTRY;
-
-        /* remote client request always pack ptlrpc_user_desc! */
-        LASSERT(pud);
-        LASSERT(perm);
-
-        if (!med->med_rmtclient)
-                RETURN(-EBADE);
-
-        perm->rp_uid = pud->pud_uid;
-        perm->rp_gid = pud->pud_gid;
-        perm->rp_fsuid = pud->pud_fsuid;
-        perm->rp_fsgid = pud->pud_fsgid;
-
-        rc = mdt_remote_perm_reverse_idmap(req, perm);
-        if (rc)
-                RETURN(rc);
-
-        return mo_permission(ctxt, &info->mti_uc, next,
-                             (MAY_EXEC | MAY_WRITE | MAY_READ),
-                             &perm->rp_access_perm);
-}
-#endif
index 88f67fe..af49819 100644 (file)
@@ -390,9 +390,6 @@ int mdt_handle_idmap(struct mdt_thread_info *info)
         if (!med->med_rmtclient)
                 RETURN(0);
 
-        if (req->rq_auth_usr_mdt)
-                RETURN(0);
-
         opc = lustre_msg_get_opc(req->rq_reqmsg);
         /* Bypass other opc */
         if ((opc != SEC_CTX_INIT) && (opc != SEC_CTX_INIT_CONT) &&
@@ -517,9 +514,6 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         if (!med->med_rmtclient)
                 return 0;
 
-        if (req->rq_auth_usr_mdt)
-                return 0;
-
         uid = mdt_idmap_lookup_uid(idmap, 0, pud->pud_uid);
         if (uid == MDT_IDMAP_NOTFOUND) {
                 CERROR("no mapping for uid %u\n", pud->pud_uid);
@@ -557,21 +551,6 @@ int ptlrpc_user_desc_do_idmap(struct ptlrpc_request *req,
         pud->pud_fsuid = fsuid;
         pud->pud_fsgid = fsgid;
 
-#if 0
-        /* remote client doesn't support setgroups */
-        if (med->med_rmtclient)
-                return 0;
-
-        for (i = 0; i < pud->pud_ngroups; i++) {
-                gid = mdt_idmap_lookup_gid(idmap, 0, pud->pud_groups[i]);
-                if (gid == MDT_IDMAP_NOTFOUND) {
-                        CERROR("no mapping for gid %u\n", pud->pud_gid);
-                        return -EACCES;
-                }
-                pud->pud_groups[i] = gid;
-        }
-#endif
-
         return 0;
 }
 
@@ -588,16 +567,18 @@ void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
         if (!med->med_rmtclient)
                 return;
 
-        if (req->rq_auth_usr_mdt)
-                return;
-
         if (body->valid & OBD_MD_FLUID) {
-                if (body->uid == uc->mu_uid)
-                        uid = uc->mu_o_uid;
-                else if (body->uid == uc->mu_fsuid)
-                        uid = uc->mu_o_fsuid;
-                else
+                if ((uc->mu_valid == UCRED_OLD) ||
+                    (uc->mu_valid == UCRED_NEW)) {
+                        if (body->uid == uc->mu_uid)
+                                uid = uc->mu_o_uid;
+                        else if (body->uid == uc->mu_fsuid)
+                                uid = uc->mu_o_fsuid;
+                        else
+                                uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
+                } else {
                         uid = mdt_idmap_lookup_uid(idmap, 1, body->uid);
+                }
 
                 if (uid == MDT_IDMAP_NOTFOUND) {
                         uid = med->med_nllu;
@@ -610,12 +591,17 @@ void mdt_body_reverse_idmap(struct mdt_thread_info *info, struct mdt_body *body)
         }
 
         if (body->valid & OBD_MD_FLGID) {
-                if (body->gid == uc->mu_gid)
-                        gid = uc->mu_o_gid;
-                else if (body->gid == uc->mu_fsgid)
-                        gid = uc->mu_o_fsgid;
-                else
+                if ((uc->mu_valid == UCRED_OLD) ||
+                    (uc->mu_valid == UCRED_NEW)) {
+                        if (body->gid == uc->mu_gid)
+                                gid = uc->mu_o_gid;
+                        else if (body->gid == uc->mu_fsgid)
+                                gid = uc->mu_o_fsgid;
+                        else
+                                gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
+                } else {
                         gid = mdt_idmap_lookup_gid(idmap, 1, body->gid);
+                }
 
                 if (gid == MDT_IDMAP_NOTFOUND) {
                         gid = med->med_nllg;
@@ -687,8 +673,8 @@ int mdt_fix_attr_ucred(struct mdt_thread_info *info, __u32 op)
         if (!med->med_rmtclient)
                 RETURN(0);
 
-        if (req->rq_auth_usr_mdt)
-                RETURN(0);
+        if ((uc->mu_valid != UCRED_OLD) && (uc->mu_valid != UCRED_NEW))
+                RETURN(-EINVAL);
 
         if (op != REINT_SETATTR) {
                 if ((attr->la_valid & LA_UID) && (attr->la_uid != -1))
index 6ff3450..adfe5ac 100644 (file)
 #include "mdt_internal.h"
 
 
+typedef enum ucred_init_type {
+        BODY_INIT       = 0,
+        REC_INIT        = 1,
+} ucred_init_type_t;
+
 int groups_from_list(struct group_info *ginfo, gid_t *glist)
 {
         int i;
@@ -96,6 +101,7 @@ void mdt_exit_ucred(struct mdt_thread_info *info)
         struct mdt_device *mdt = info->mti_mdt;
 
         if (uc->mu_valid != UCRED_INIT) {
+                uc->mu_suppgids[0] = uc->mu_suppgids[1] = -1;
                 if (uc->mu_ginfo) {
                         groups_free(uc->mu_ginfo);
                         uc->mu_ginfo = NULL;
@@ -109,35 +115,93 @@ void mdt_exit_ucred(struct mdt_thread_info *info)
         }
 }
 
+static int old_init_ucred(struct mdt_thread_info *info,
+                          struct mdt_body *body)
+{
+        struct md_ucred     *uc = &info->mti_uc;
+        struct mdt_device   *mdt = info->mti_mdt;
+        struct mdt_identity *identity = NULL;
+
+        ENTRY;
+
+        uc->mu_valid = UCRED_INVALID;
+
+        if (!mdt->no_gss_support) {
+                /* get identity info of this user */
+                identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                            body->fsuid);
+                if (!identity) {
+                        CERROR("Deny access without identity: uid %d\n",
+                               body->fsuid);
+                        RETURN(-EACCES);
+                }
+        }
+
+        uc->mu_valid = UCRED_OLD;
+        uc->mu_o_uid = uc->mu_uid = body->uid;
+        uc->mu_o_gid = uc->mu_gid = body->gid;
+        uc->mu_o_fsuid = uc->mu_fsuid = body->fsuid;
+        uc->mu_o_fsgid = uc->mu_fsgid = body->fsgid;
+        uc->mu_suppgids[0] = body->suppgid;
+        uc->mu_suppgids[1] = -1;
+        uc->mu_cap = body->capability;
+        uc->mu_ginfo = NULL;
+        uc->mu_identity = identity;
+
+        RETURN(0);
+}
+
+static int old_init_ucred_reint(struct mdt_thread_info *info)
+{
+        struct md_ucred     *uc = &info->mti_uc;
+        struct mdt_device   *mdt = info->mti_mdt;
+        struct mdt_identity *identity = NULL;
+
+        ENTRY;
+
+        uc->mu_valid = UCRED_INVALID;
+
+        if (!mdt->no_gss_support) {
+                /* get identity info of this user */
+                identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                            uc->mu_fsuid);
+                if (!identity) {
+                        CERROR("Deny access without identity: uid %d\n",
+                               uc->mu_fsuid);
+                        RETURN(-EACCES);
+                }
+        }
+
+        uc->mu_valid = UCRED_OLD;
+        uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
+        uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
+        uc->mu_ginfo = NULL;
+        uc->mu_identity = identity;
+
+        RETURN(0);
+}
+
 static int nid_nosquash(struct mdt_device *mdt, lnet_nid_t nid)
 {
         struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
         int i;
 
         for (i = 0; i < rsi->rsi_n_nosquash_nids; i++)
-                if (rsi->rsi_nosquash_nids[i] == nid ||
-                    rsi->rsi_nosquash_nids[i] == LNET_NID_ANY)
+                if ((rsi->rsi_nosquash_nids[i] == nid) ||
+                    (rsi->rsi_nosquash_nids[i] == LNET_NID_ANY))
                         return 1;
 
         return 0;
 }
 
-/*
- * FIXME: here we follow simple rule: once uid/fsuid is root, we also squash
- *        the gid/fsgid, don't care setuid/setgid attributes.
- *
- * NB: don't change pud fields in root squash, because xid in pud will be
- *     packed in remote perm reply.
- */
 static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
                            struct ptlrpc_user_desc *pud, lnet_nid_t peernid)
 {
         struct rootsquash_info *rsi = mdt->mdt_rootsquash_info;
+        int squash_count = 0;
 
-        if (pud->pud_uid && pud->pud_fsuid)
-                return 0;
-
-        if (!rsi || !rsi->rsi_uid || nid_nosquash(mdt, peernid))
+        if (!rsi || (!rsi->rsi_uid && !rsi->rsi_gid) ||
+            nid_nosquash(mdt, peernid))
                 return 0;
 
         CDEBUG(D_SEC, "squash req from "LPX64":"
@@ -150,28 +214,64 @@ static int mdt_squash_root(struct mdt_device *mdt, struct md_ucred *ucred,
                pud->pud_fsuid ? pud->pud_fsgid : rsi->rsi_gid,
                pud->pud_cap & ~CAP_FS_MASK);
 
-        if (pud->pud_uid == 0) {
-                ucred->mu_uid = rsi->rsi_uid;
-                ucred->mu_gid = rsi->rsi_gid;
-        } else {
-                ucred->mu_uid = pud->pud_uid;
-                ucred->mu_gid = pud->pud_gid;
+        if (rsi->rsi_uid) {
+                if (!pud->pud_uid) {
+                        ucred->mu_uid = rsi->rsi_uid;
+                        squash_count++;
+                } else {
+                        ucred->mu_uid = pud->pud_uid;
+                }
+
+                if (!pud->pud_fsuid) {
+                        ucred->mu_fsuid = rsi->rsi_uid;
+                        squash_count++;
+                } else {
+                        ucred->mu_fsuid = pud->pud_fsuid;
+                }
         }
 
-        if (pud->pud_fsuid == 0) {
-                ucred->mu_fsuid = rsi->rsi_uid;
-                ucred->mu_fsgid = rsi->rsi_gid;
-        } else {
-                ucred->mu_fsuid = pud->pud_fsuid;
-                ucred->mu_fsgid = pud->pud_fsgid;
+        if (rsi->rsi_gid) {
+                int i;
+
+                if (!pud->pud_gid) {
+                        ucred->mu_gid = rsi->rsi_gid;
+                        squash_count++;
+                } else {
+                        ucred->mu_gid = pud->pud_gid;
+                }
+
+                if (!pud->pud_fsgid) {
+                        ucred->mu_fsgid = rsi->rsi_gid;
+                        squash_count++;
+                } else {
+                        ucred->mu_fsgid = pud->pud_fsgid;
+                }
+
+                for (i = 0; i < 2; i++) {
+                        if (!ucred->mu_suppgids[i]) {
+                                ucred->mu_suppgids[i] = rsi->rsi_gid;
+                                squash_count++;
+                        }
+                }
+
+                for (i = 0; i < pud->pud_ngroups; i++) {
+                        if (!pud->pud_groups[i]) {
+                                pud->pud_groups[i] = rsi->rsi_gid;
+                                squash_count++;
+                        }
+                }
         }
 
-        ucred->mu_cap &= (pud->pud_cap & ~CAP_FS_MASK);
+        if (squash_count || ucred->mu_fsuid)
+                ucred->mu_cap = (pud->pud_cap & ~CAP_FS_MASK);
+        else
+                ucred->mu_cap = pud->pud_cap;
 
         return 1;
 }
 
-static int new_init_ucred(struct mdt_thread_info *info)
+static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
+                          void *buf)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct mdt_export_data  *med = mdt_req2med(req);
@@ -182,6 +282,8 @@ static int new_init_ucred(struct mdt_thread_info *info)
         lnet_nid_t              peernid = req->rq_peer.nid;
         __u32                   setxid_perm = 0;
         int                     root_squashed = 0;
+        int                     setuid;
+        int                     setgid;
         int                     rc = 0;
 
         ENTRY;
@@ -199,11 +301,32 @@ static int new_init_ucred(struct mdt_thread_info *info)
                 RETURN(-EACCES);
         }
 
+        if (req->rq_auth_usr_mdt) {
+                switch (type) {
+                case BODY_INIT:
+                        ucred->mu_valid = UCRED_INIT;
+                        RETURN(old_init_ucred(info, (struct mdt_body *)buf));
+                case REC_INIT:
+                        ucred->mu_valid = UCRED_INIT;
+                        RETURN(old_init_ucred_reint(info));
+                default:
+                        CWARN("Invalid ucred init type\n");
+                        RETURN(-EINVAL);
+                }
+        }
+
         ucred->mu_o_uid   = pud->pud_uid;
         ucred->mu_o_gid   = pud->pud_gid;
         ucred->mu_o_fsuid = pud->pud_fsuid;
         ucred->mu_o_fsgid = pud->pud_fsgid;
 
+        if (type == BODY_INIT) {
+                struct mdt_body *body = (struct mdt_body *)buf;
+
+                ucred->mu_suppgids[0] = body->suppgid;
+                ucred->mu_suppgids[1] = -1;
+        }
+
         /* sanity check: if we use strong authentication, we expect the
          * uid which client claimed is true */
         if (req->rq_auth_gss) {
@@ -241,40 +364,34 @@ static int new_init_ucred(struct mdt_thread_info *info)
                 RETURN(-EACCES);
         }
 
-        /* check setuid/setgid permissions */
-        if (!req->rq_auth_usr_mdt) {
-                int setuid, setgid;
+        /* find out the setuid/setgid attempt */
+        setuid = (pud->pud_uid != pud->pud_fsuid);
+        setgid = (pud->pud_gid != pud->pud_fsgid ||
+                  pud->pud_gid != identity->mi_gid);
 
-                /* find out the setuid/setgid attempt */
-                setuid = (pud->pud_uid != pud->pud_fsuid);
-                setgid = (pud->pud_gid != pud->pud_fsgid ||
-                          pud->pud_gid != identity->mi_gid);
+        setxid_perm = mdt_identity_get_setxid_perm(identity,
+                                                   med->med_rmtclient,
+                                                   peernid);
 
-                setxid_perm = mdt_identity_get_setxid_perm(identity,
-                                                           med->med_rmtclient,
-                                                           peernid);
-
-                /* check permission of setuid */
-                if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
-                        CWARN("mdt blocked setuid attempt (%u -> %u) from "
-                              LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
-                        GOTO(out, rc = -EACCES);
-                }
+        /* check permission of setuid */
+        if (setuid && !(setxid_perm & LUSTRE_SETUID_PERM)) {
+                CWARN("mdt blocked setuid attempt (%u -> %u) from "
+                      LPX64"\n", pud->pud_uid, pud->pud_fsuid, peernid);
+                GOTO(out, rc = -EACCES);
+        }
 
-                /* check permission of setgid */
-                if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
-                        CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
-                              "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
-                              pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
-                              peernid);
-                        GOTO(out, rc = -EACCES);
-                }
+        /* check permission of setgid */
+        if (setgid && !(setxid_perm & LUSTRE_SETGID_PERM)) {
+                CWARN("mdt blocked setgid attempt (%u:%u/%u:%u -> %u) "
+                      "from "LPX64"\n", pud->pud_uid, pud->pud_gid,
+                      pud->pud_fsuid, pud->pud_fsgid, identity->mi_gid,
+                      peernid);
+                GOTO(out, rc = -EACCES);
         }
 
 check_squash:
         /* FIXME: The exact behavior of root_squash is not defined. */
-        if (!req->rq_auth_usr_mdt)
-                root_squashed = mdt_squash_root(mdt, ucred, pud, peernid);
+        root_squashed = mdt_squash_root(mdt, ucred, pud, peernid);
         if (!root_squashed) {
                 ucred->mu_uid   = pud->pud_uid;
                 ucred->mu_gid   = pud->pud_gid;
@@ -286,17 +403,11 @@ check_squash:
                         ucred->mu_cap &= ~CAP_FS_MASK;
         }
 
-        /* by now every fields other than groups have been granted */
-        ucred->mu_identity = identity;
-
-        /* setgroups for local client with LUSTRE_SETGRP_PERM, and no_squash_
-         * root, otherwise install groups from local user supplementary groups.
-         *
+        /*
          * NB: remote client not allowed to setgroups anyway.
          */
-        if (req->rq_auth_usr_mdt ||
-            (pud->pud_ngroups && !med->med_rmtclient && !root_squashed &&
-            (setxid_perm & LUSTRE_SETGRP_PERM))) {
+        if (pud->pud_ngroups && !med->med_rmtclient &&
+            ((setxid_perm & LUSTRE_SETGRP_PERM) || mdt->no_gss_support)) {
                 struct group_info *ginfo;
 
                 /* setgroups for local client */
@@ -313,6 +424,7 @@ check_squash:
                 ucred->mu_ginfo = NULL;
         }
 
+        ucred->mu_identity = identity;
         ucred->mu_valid = UCRED_NEW;
 
 out:
@@ -322,44 +434,6 @@ out:
         RETURN(rc);
 }
 
-static int old_init_ucred(struct mdt_thread_info *info,
-                          struct mdt_body *body)
-{
-        struct md_ucred     *uc = &info->mti_uc;
-        struct mdt_device   *mdt = info->mti_mdt;
-        struct mdt_identity *identity = NULL;
-
-        ENTRY;
-
-        uc->mu_valid = UCRED_INVALID;
-
-        if (!mdt->no_gss_support) {
-                /* get identity info of this user */
-                identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            body->fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               body->fsuid);
-                        RETURN(-EACCES);
-                }
-        }
-
-        uc->mu_valid = UCRED_OLD;
-        uc->mu_o_uid = body->uid;
-        uc->mu_o_gid = body->gid;
-        uc->mu_o_fsuid = body->fsuid;
-        uc->mu_o_fsgid = body->fsgid;
-        uc->mu_uid = body->uid;
-        uc->mu_gid = body->gid;
-        uc->mu_fsuid = body->fsuid;
-        uc->mu_fsgid = body->fsgid;
-        uc->mu_cap = body->capability;
-        uc->mu_ginfo = NULL;
-        uc->mu_identity = identity;
-
-        RETURN(0);
-}
-
 int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
@@ -371,40 +445,10 @@ int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
         mdt_exit_ucred(info);
 
         /* !rq_user_desc means null security */
-        return req->rq_user_desc ? new_init_ucred(info) :
+        return req->rq_user_desc ? new_init_ucred(info, BODY_INIT, body) :
                                    old_init_ucred(info, body);
 }
 
-static int old_init_ucred_reint(struct mdt_thread_info *info)
-{
-        struct md_ucred     *uc = &info->mti_uc;
-        struct mdt_device   *mdt = info->mti_mdt;
-        struct mdt_identity *identity = NULL;
-
-        ENTRY;
-
-        uc->mu_valid = UCRED_INVALID;
-
-        if (!mdt->no_gss_support) {
-                /* get identity info of this user */
-                identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            uc->mu_fsuid);
-                if (!identity) {
-                        CERROR("Deny access without identity: uid %d\n",
-                               uc->mu_fsuid);
-                        RETURN(-EACCES);
-                }
-        }
-
-        uc->mu_valid = UCRED_OLD;
-        uc->mu_o_uid = uc->mu_o_fsuid = uc->mu_uid = uc->mu_fsuid;
-        uc->mu_o_gid = uc->mu_o_fsgid = uc->mu_gid = uc->mu_fsgid;
-        uc->mu_ginfo = NULL;
-        uc->mu_identity = identity;
-
-        RETURN(0);
-}
-
 int mdt_init_ucred_reint(struct mdt_thread_info *info)
 {
         struct ptlrpc_request *req = mdt_info_req(info);
@@ -416,7 +460,7 @@ int mdt_init_ucred_reint(struct mdt_thread_info *info)
         mdt_exit_ucred(info);
 
         /* !rq_user_desc means null security */
-        return req->rq_user_desc ? new_init_ucred(info) :
+        return req->rq_user_desc ? new_init_ucred(info, REC_INIT, NULL) :
                                    old_init_ucred_reint(info);
 }
 
@@ -565,6 +609,8 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
         uc->mu_uid   = rec->sa_uid;
         uc->mu_gid   = rec->sa_gid;
         uc->mu_cap   = rec->sa_cap;
+        uc->mu_suppgids[0] = rec->sa_suppgid;
+        uc->mu_suppgids[1] = -1;
  
         rr->rr_fid1 = &rec->sa_fid;
         la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
@@ -655,6 +701,8 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
                 uc->mu_fsuid = rec->cr_fsuid;
                 uc->mu_fsgid = rec->cr_fsgid;
                 uc->mu_cap   = rec->cr_cap;
+                uc->mu_suppgids[0] = rec->cr_suppgid;
+                uc->mu_suppgids[1] = -1;
  
                 rr->rr_fid1 = &rec->cr_fid1;
                 rr->rr_fid2 = &rec->cr_fid2;
@@ -720,6 +768,8 @@ static int mdt_link_unpack(struct mdt_thread_info *info)
                 uc->mu_fsuid = rec->lk_fsuid;
                 uc->mu_fsgid = rec->lk_fsgid;
                 uc->mu_cap   = rec->lk_cap;
+                uc->mu_suppgids[0] = rec->lk_suppgid1;
+                uc->mu_suppgids[1] = rec->lk_suppgid2;
  
                 attr->la_uid = rec->lk_fsuid;
                 attr->la_gid = rec->lk_fsgid;
@@ -751,6 +801,8 @@ static int mdt_unlink_unpack(struct mdt_thread_info *info)
                 uc->mu_fsuid = rec->ul_fsuid;
                 uc->mu_fsgid = rec->ul_fsgid;
                 uc->mu_cap   = rec->ul_cap;
+                uc->mu_suppgids[0] = rec->ul_suppgid;
+                uc->mu_suppgids[1] = -1;
  
                 attr->la_uid = rec->ul_fsuid;
                 attr->la_gid = rec->ul_fsgid;
@@ -785,6 +837,8 @@ static int mdt_rename_unpack(struct mdt_thread_info *info)
                 uc->mu_fsuid = rec->rn_fsuid;
                 uc->mu_fsgid = rec->rn_fsgid;
                 uc->mu_cap   = rec->rn_cap;
+                uc->mu_suppgids[0] = rec->rn_suppgid1;
+                uc->mu_suppgids[1] = rec->rn_suppgid2;
  
                 attr->la_uid = rec->rn_fsuid;
                 attr->la_gid = rec->rn_fsgid;
@@ -820,6 +874,8 @@ static int mdt_open_unpack(struct mdt_thread_info *info)
                 uc->mu_fsuid = rec->cr_fsuid;
                 uc->mu_fsgid = rec->cr_fsgid;
                 uc->mu_cap   = rec->cr_cap;
+                uc->mu_suppgids[0] = rec->cr_suppgid;
+                uc->mu_suppgids[1] = -1;
  
                 rr->rr_fid1   = &rec->cr_fid1;
                 rr->rr_fid2   = &rec->cr_fid2;