Whamcloud - gitweb
LU-5564 mdt: skip permission check for close
[fs/lustre-release.git] / lustre / mdt / mdt_lib.c
index 574ea5e..eb08efc 100644 (file)
@@ -149,7 +149,6 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
        struct lu_ucred         *ucred = mdt_ucred(info);
         lnet_nid_t               peernid = req->rq_peer.nid;
         __u32                    perm = 0;
-        __u32                    remote = exp_connect_rmtclient(info->mti_exp);
         int                      setuid;
         int                      setgid;
         int                      rc = 0;
@@ -175,71 +174,44 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                ucred->uc_suppgids[1] = -1;
        }
 
-       /* sanity check: we expect the uid which client claimed is true */
-       if (remote) {
-               if (!uid_valid(make_kuid(&init_user_ns, req->rq_auth_mapped_uid))) {
-                       CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
-                       RETURN(-EACCES);
-               }
-
-               if (ptlrpc_user_desc_do_idmap(req, pud))
-                       RETURN(-EACCES);
-
-                if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                        CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
-                               "while client claims %u:%u/%u:%u\n",
-                               libcfs_nid2str(peernid), req->rq_auth_uid,
-                               req->rq_auth_mapped_uid,
-                               pud->pud_uid, pud->pud_gid,
-                               pud->pud_fsuid, pud->pud_fsgid);
-                        RETURN(-EACCES);
-                }
-        } else {
-                if (req->rq_auth_uid != pud->pud_uid) {
-                        CDEBUG(D_SEC, "local client %s: auth uid %u "
-                               "while client claims %u:%u/%u:%u\n",
-                               libcfs_nid2str(peernid), req->rq_auth_uid,
-                               pud->pud_uid, pud->pud_gid,
-                               pud->pud_fsuid, pud->pud_fsgid);
-                        RETURN(-EACCES);
-                }
-        }
+       if (!flvr_is_rootonly(req->rq_flvr.sf_rpc) &&
+           req->rq_auth_uid != pud->pud_uid) {
+               CDEBUG(D_SEC, "local client %s: auth uid %u "
+                      "while client claims %u:%u/%u:%u\n",
+                      libcfs_nid2str(peernid), req->rq_auth_uid,
+                      pud->pud_uid, pud->pud_gid,
+                      pud->pud_fsuid, pud->pud_fsgid);
+               RETURN(-EACCES);
+       }
 
-        if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
-                if (remote) {
-                        CDEBUG(D_SEC, "remote client must run with identity_get "
-                               "enabled!\n");
-                        RETURN(-EACCES);
-                } else {
-                       ucred->uc_identity = NULL;
-                        perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
-                               CFS_SETGRP_PERM;
-                }
-        } else {
-                struct md_identity *identity;
+       if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
+               ucred->uc_identity = NULL;
+               perm = CFS_SETUID_PERM | CFS_SETGID_PERM | CFS_SETGRP_PERM;
+       } else {
+               struct md_identity *identity;
 
-                identity = mdt_identity_get(mdt->mdt_identity_cache,
-                                            pud->pud_uid);
-                if (IS_ERR(identity)) {
-                        if (unlikely(PTR_ERR(identity) == -EREMCHG &&
-                                     !remote)) {
+               identity = mdt_identity_get(mdt->mdt_identity_cache,
+                                           pud->pud_uid);
+               if (IS_ERR(identity)) {
+                       if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
                                ucred->uc_identity = NULL;
-                                perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
-                                       CFS_SETGRP_PERM;
-                        } else {
-                                CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
-                                       pud->pud_uid);
-                                RETURN(-EACCES);
-                        }
-                } else {
+                               perm = CFS_SETUID_PERM | CFS_SETGID_PERM |
+                                      CFS_SETGRP_PERM;
+                       } else {
+                               CDEBUG(D_SEC,
+                                      "Deny access without identity: uid %u\n",
+                                      pud->pud_uid);
+                               RETURN(-EACCES);
+                       }
+               } else {
                        ucred->uc_identity = identity;
                        perm = mdt_identity_get_perm(ucred->uc_identity,
-                                                    remote, peernid);
-                }
-        }
+                                                    peernid);
+               }
+       }
 
-        /* find out the setuid/setgid attempt */
-        setuid = (pud->pud_uid != pud->pud_fsuid);
+       /* find out the setuid/setgid attempt */
+       setuid = (pud->pud_uid != pud->pud_fsuid);
        setgid = ((pud->pud_gid != pud->pud_fsgid) ||
                  (ucred->uc_identity &&
                   (pud->pud_gid != ucred->uc_identity->mi_gid)));
@@ -260,10 +232,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                GOTO(out, rc = -EACCES);
         }
 
-        /*
-         * NB: remote client not allowed to setgroups anyway.
-         */
-       if (!remote && perm & CFS_SETGRP_PERM) {
+       if (perm & CFS_SETGRP_PERM) {
                if (pud->pud_ngroups) {
                        /* setgroups for local client */
                        ucred->uc_ginfo = groups_alloc(pud->pud_ngroups);
@@ -298,9 +267,6 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
                ucred->uc_cap = pud->pud_cap & ~CFS_CAP_FS_MASK;
        else
                ucred->uc_cap = pud->pud_cap;
-       if (remote && !(perm & CFS_RMTOWN_PERM))
-               ucred->uc_cap &= ~(CFS_CAP_SYS_RESOURCE_MASK |
-                                  CFS_CAP_CHOWN_MASK);
        ucred->uc_valid = UCRED_NEW;
        ucred_set_jobid(info, ucred);
 
@@ -333,17 +299,12 @@ out:
  */
 bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc)
 {
-       __u32 remote = exp_connect_rmtclient(info->mti_exp);
        __u32 perm;
 
-       /* 1. If identity_upcall is disabled, then forbid remote client to set
-        *    supplementary group IDs, but permit local client to do that. */
-       if (is_identity_get_disabled(info->mti_mdt->mdt_identity_cache)) {
-               if (remote)
-                       return false;
-
+       /* 1. If identity_upcall is disabled,
+        *    permit local client to do anything. */
+       if (is_identity_get_disabled(info->mti_mdt->mdt_identity_cache))
                return true;
-       }
 
        /* 2. If fail to get related identities, then forbid any client to
         *    set supplementary group IDs. */
@@ -351,7 +312,7 @@ bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc)
                return false;
 
        /* 3. Check the permission in the identities. */
-       perm = mdt_identity_get_perm(uc->uc_identity, remote,
+       perm = mdt_identity_get_perm(uc->uc_identity,
                                     mdt_info_req(info)->rq_peer.nid);
        if (perm & CFS_SETGRP_PERM)
                return true;
@@ -368,7 +329,6 @@ int mdt_check_ucred(struct mdt_thread_info *info)
         struct md_identity      *identity = NULL;
         lnet_nid_t               peernid = req->rq_peer.nid;
         __u32                    perm = 0;
-        __u32                    remote = exp_connect_rmtclient(info->mti_exp);
         int                      setuid;
         int                      setgid;
         int                      rc = 0;
@@ -379,62 +339,36 @@ int mdt_check_ucred(struct mdt_thread_info *info)
        if ((ucred->uc_valid == UCRED_OLD) || (ucred->uc_valid == UCRED_NEW))
                RETURN(0);
 
-        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
-                RETURN(0);
-
-        /* sanity check: if we use strong authentication, we expect the
-         * uid which client claimed is true */
-        if (remote) {
-               if (!uid_valid(make_kuid(&init_user_ns, req->rq_auth_mapped_uid))) {
-                        CDEBUG(D_SEC, "remote user not mapped, deny access!\n");
-                        RETURN(-EACCES);
-                }
+       if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
+               RETURN(0);
 
-                if (ptlrpc_user_desc_do_idmap(req, pud))
-                        RETURN(-EACCES);
-
-                if (req->rq_auth_mapped_uid != pud->pud_uid) {
-                        CDEBUG(D_SEC, "remote client %s: auth/mapped uid %u/%u "
-                               "while client claims %u:%u/%u:%u\n",
-                               libcfs_nid2str(peernid), req->rq_auth_uid,
-                               req->rq_auth_mapped_uid,
-                               pud->pud_uid, pud->pud_gid,
-                               pud->pud_fsuid, pud->pud_fsgid);
-                        RETURN(-EACCES);
-                }
-        } else {
-                if (req->rq_auth_uid != pud->pud_uid) {
-                        CDEBUG(D_SEC, "local client %s: auth uid %u "
-                               "while client claims %u:%u/%u:%u\n",
-                               libcfs_nid2str(peernid), req->rq_auth_uid,
-                               pud->pud_uid, pud->pud_gid,
-                               pud->pud_fsuid, pud->pud_fsgid);
-                        RETURN(-EACCES);
-                }
-        }
+       /* sanity check: if we use strong authentication, we expect the
+        * uid which client claimed is true */
+       if (!flvr_is_rootonly(req->rq_flvr.sf_rpc) &&
+           req->rq_auth_uid != pud->pud_uid) {
+               CDEBUG(D_SEC, "local client %s: auth uid %u "
+                      "while client claims %u:%u/%u:%u\n",
+                      libcfs_nid2str(peernid), req->rq_auth_uid,
+                      pud->pud_uid, pud->pud_gid,
+                      pud->pud_fsuid, pud->pud_fsgid);
+               RETURN(-EACCES);
+       }
 
-        if (is_identity_get_disabled(mdt->mdt_identity_cache)) {
-                if (remote) {
-                        CDEBUG(D_SEC, "remote client must run with identity_get "
-                               "enabled!\n");
-                        RETURN(-EACCES);
-                }
-                RETURN(0);
-        }
+       if (is_identity_get_disabled(mdt->mdt_identity_cache))
+               RETURN(0);
 
-        identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
-        if (IS_ERR(identity)) {
-                if (unlikely(PTR_ERR(identity) == -EREMCHG &&
-                             !remote)) {
-                        RETURN(0);
-                } else {
-                        CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
-                               pud->pud_uid);
-                        RETURN(-EACCES);
-               }
-        }
+       identity = mdt_identity_get(mdt->mdt_identity_cache, pud->pud_uid);
+       if (IS_ERR(identity)) {
+               if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
+                       RETURN(0);
+               } else {
+                       CDEBUG(D_SEC, "Deny access without identity: uid %u\n",
+                              pud->pud_uid);
+                       RETURN(-EACCES);
+               }
+       }
 
-        perm = mdt_identity_get_perm(identity, remote, peernid);
+       perm = mdt_identity_get_perm(identity, peernid);
         /* find out the setuid/setgid attempt */
         setuid = (pud->pud_uid != pud->pud_fsuid);
         setgid = (pud->pud_gid != pud->pud_fsgid ||
@@ -464,26 +398,19 @@ out:
 }
 
 static int old_init_ucred_common(struct mdt_thread_info *info,
-                                 bool drop_fs_cap)
+                                struct lu_nodemap *nodemap,
+                                bool drop_fs_cap)
 {
        struct lu_ucred         *uc = mdt_ucred(info);
        struct mdt_device       *mdt = info->mti_mdt;
        struct md_identity      *identity = NULL;
-       struct lu_nodemap       *nodemap =
-               info->mti_exp->exp_target_data.ted_nodemap;
-
-       if (nodemap == NULL) {
-               CDEBUG(D_SEC, "%s: cli %s/%p nodemap not set.\n",
-                      mdt2obd_dev(mdt)->obd_name,
-                      info->mti_exp->exp_client_uuid.uuid, info->mti_exp);
-               RETURN(-EACCES);
-       }
 
        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
                identity = mdt_identity_get(mdt->mdt_identity_cache,
                                            uc->uc_fsuid);
                if (IS_ERR(identity)) {
-                       if (unlikely(PTR_ERR(identity) == -EREMCHG)) {
+                       if (unlikely(PTR_ERR(identity) == -EREMCHG ||
+                                    uc->uc_cap & CFS_CAP_FS_MASK)) {
                                identity = NULL;
                        } else {
                                CDEBUG(D_SEC, "Deny access without identity: "
@@ -494,7 +421,7 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
        }
        uc->uc_identity = identity;
 
-       if (uc->uc_o_uid == nodemap->nm_squash_uid) {
+       if (nodemap && uc->uc_o_uid == nodemap->nm_squash_uid) {
                uc->uc_fsuid = nodemap->nm_squash_uid;
                uc->uc_fsgid = nodemap->nm_squash_gid;
                uc->uc_cap = 0;
@@ -506,7 +433,7 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
        mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
 
        /* remove fs privilege for non-root user. */
-       if (uc->uc_fsuid)
+       if (uc->uc_fsuid && drop_fs_cap)
                uc->uc_cap &= ~CFS_CAP_FS_MASK;
        uc->uc_valid = UCRED_OLD;
        ucred_set_jobid(info, uc);
@@ -517,12 +444,15 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
 static int old_init_ucred(struct mdt_thread_info *info,
                          struct mdt_body *body, bool drop_fs_cap)
 {
-       struct lu_ucred         *uc = mdt_ucred(info);
-       struct lu_nodemap       *nodemap =
-               info->mti_exp->exp_target_data.ted_nodemap;
-       int                      rc;
+       struct lu_ucred *uc = mdt_ucred(info);
+       struct lu_nodemap *nodemap;
+       int rc;
        ENTRY;
 
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+
        body->mbo_uid = nodemap_map_id(nodemap, NODEMAP_UID,
                                       NODEMAP_CLIENT_TO_FS, body->mbo_uid);
        body->mbo_gid = nodemap_map_id(nodemap, NODEMAP_GID,
@@ -543,19 +473,23 @@ static int old_init_ucred(struct mdt_thread_info *info,
        uc->uc_ginfo = NULL;
        uc->uc_cap = body->mbo_capability;
 
-       rc = old_init_ucred_common(info, drop_fs_cap);
+       rc = old_init_ucred_common(info, nodemap, drop_fs_cap);
+       nodemap_putref(nodemap);
 
        RETURN(rc);
 }
 
 static int old_init_ucred_reint(struct mdt_thread_info *info)
 {
-       struct lu_ucred         *uc = mdt_ucred(info);
-       struct lu_nodemap       *nodemap =
-               info->mti_exp->exp_target_data.ted_nodemap;
-       int                      rc;
+       struct lu_ucred *uc = mdt_ucred(info);
+       struct lu_nodemap *nodemap;
+       int rc;
        ENTRY;
 
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+
        LASSERT(uc != NULL);
 
        uc->uc_fsuid = nodemap_map_id(nodemap, NODEMAP_UID,
@@ -568,7 +502,8 @@ static int old_init_ucred_reint(struct mdt_thread_info *info)
        uc->uc_o_gid = uc->uc_o_fsgid = uc->uc_gid = uc->uc_fsgid;
        uc->uc_ginfo = NULL;
 
-       rc = old_init_ucred_common(info, true); /* drop_fs_cap = true */
+       rc = old_init_ucred_common(info, nodemap, true); /* drop_fs_cap=true */
+       nodemap_putref(nodemap);
 
        RETURN(rc);
 }
@@ -612,11 +547,17 @@ int mdt_init_ucred_reint(struct mdt_thread_info *info)
 {
        struct ptlrpc_request *req = mdt_info_req(info);
        struct lu_ucred       *uc  = mdt_ucred(info);
+       struct md_attr        *ma  = &info->mti_attr;
 
        LASSERT(uc != NULL);
        if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW))
                return 0;
 
+       /* LU-5564: for normal close request, skip permission check */
+       if (lustre_msg_get_opc(req->rq_reqmsg) == MDS_CLOSE &&
+           !(ma->ma_attr_flags & (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP)))
+               uc->uc_cap |= CFS_CAP_FS_MASK;
+
        mdt_exit_ucred(info);
 
        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
@@ -913,8 +854,7 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
        struct req_capsule      *pill = info->mti_pill;
        struct mdt_reint_record *rr = &info->mti_rr;
        struct mdt_rec_setattr  *rec;
-       struct lu_nodemap       *nodemap =
-               info->mti_exp->exp_target_data.ted_nodemap;
+       struct lu_nodemap       *nodemap;
         ENTRY;
 
         CLASSERT(sizeof(struct mdt_rec_setattr)== sizeof(struct mdt_rec_reint));
@@ -933,10 +873,17 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
        la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
        la->la_mode  = rec->sa_mode;
        la->la_flags = rec->sa_attr_flags;
+
+       nodemap = nodemap_get_from_exp(info->mti_exp);
+       if (IS_ERR(nodemap))
+               RETURN(PTR_ERR(nodemap));
+
        la->la_uid   = nodemap_map_id(nodemap, NODEMAP_UID,
                                      NODEMAP_CLIENT_TO_FS, rec->sa_uid);
        la->la_gid   = nodemap_map_id(nodemap, NODEMAP_GID,
                                      NODEMAP_CLIENT_TO_FS, rec->sa_gid);
+       nodemap_putref(nodemap);
+
        la->la_size  = rec->sa_size;
        la->la_blocks = rec->sa_blocks;
        la->la_ctime = rec->sa_ctime;
@@ -1122,7 +1069,7 @@ static int mdt_create_unpack(struct mdt_thread_info *info)
                 if (tgt == NULL)
                         RETURN(-EFAULT);
         } else {
-                req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_RMT_ACL);
+               req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_ACL);
                if (S_ISDIR(attr->la_mode) &&
                    req_capsule_get_size(pill, &RMF_EADATA, RCL_CLIENT) > 0) {
                        sp->u.sp_ea.eadata =