Whamcloud - gitweb
LU-5564 mdt: skip permission check for close
[fs/lustre-release.git] / lustre / mdt / mdt_lib.c
index 62d9b8b..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,20 +398,12 @@ 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,
@@ -495,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;
@@ -518,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,
@@ -544,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,
@@ -569,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);
 }
@@ -613,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)
@@ -809,108 +749,23 @@ int mdt_fix_reply(struct mdt_thread_info *info)
 /* if object is dying, pack the lov/llog data,
  * parameter info->mti_attr should be valid at this point! */
 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
-                          struct md_attr *ma)
+                           const struct md_attr *ma)
 {
-       struct mdt_body      *repbody = NULL;
+        struct mdt_body       *repbody;
         const struct lu_attr *la = &ma->ma_attr;
-       struct coordinator   *cdt = &info->mti_mdt->mdt_coordinator;
-       int                  rc;
-       __u64                need = 0;
-       struct hsm_action_item hai = {
-               .hai_len = sizeof(hai),
-               .hai_action = HSMA_REMOVE,
-               .hai_extent.length = -1,
-               .hai_cookie = 0,
-               .hai_gid = 0,
-       };
-       __u64 compound_id;
-       int archive_id;
-
         ENTRY;
 
-       if (mdt_info_req(info) != NULL) {
-               repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
-               LASSERT(repbody != NULL);
-       } else {
-               CDEBUG(D_INFO, "not running in a request/reply context\n");
-       }
+        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+        LASSERT(repbody != NULL);
 
-       if ((ma->ma_valid & MA_INODE) && repbody != NULL)
+        if (ma->ma_valid & MA_INODE)
                 mdt_pack_attr2body(info, repbody, la, mdt_object_fid(mo));
 
-       if (ma->ma_valid & MA_LOV) {
+        if (ma->ma_valid & MA_LOV) {
                CERROR("No need in LOV EA upon unlink\n");
                dump_stack();
-       }
-       if (repbody != NULL)
-               repbody->mbo_eadatasize = 0;
-
-       /* Only check unlinked and archived if RAoLU and upon last close */
-       if (!cdt->cdt_remove_archive_on_last_unlink ||
-           atomic_read(&mo->mot_open_count) != 0)
-               RETURN(0);
-
-       if (ma->ma_valid & MA_INODE) {
-               if (ma->ma_attr.la_nlink != 0)
-                       RETURN(0);
-       } else {
-               need |= MA_INODE;
-       }
-
-       if (ma->ma_valid & MA_HSM) {
-               if (!(ma->ma_hsm.mh_flags & HS_EXISTS))
-                       RETURN(0);
-       } else {
-               need |= MA_HSM;
-       }
-
-       if (need != 0) {
-               ma->ma_need |= need;
-               rc = mdt_attr_get_complex(info, mo, ma);
-               if (rc) {
-                       CERROR("%s: unable to fetch missing attributes of"
-                              DFID": rc=%d\n", mdt_obd_name(info->mti_mdt),
-                              PFID(mdt_object_fid(mo)), rc);
-                       RETURN(0);
-               }
-
-               if (need & MA_INODE) {
-                       if (ma->ma_valid & MA_INODE) {
-                               if (ma->ma_attr.la_nlink != 0)
-                                       RETURN(0);
-                       } else {
-                               RETURN(0);
-                       }
-               }
-
-               if (need & MA_HSM) {
-                       if (ma->ma_valid & MA_HSM) {
-                               if (!(ma->ma_hsm.mh_flags & HS_EXISTS))
-                                       RETURN(0);
-                       } else {
-                               RETURN(0);
-                       }
-               }
-       }
-
-       /* RAoLU policy is active, last close on file has occured,
-        * file is unlinked, file is archived, so create remove request
-        * for copytool!
-        * If CDT is not running, requests will be logged for later. */
-       compound_id = atomic_inc_return(&cdt->cdt_compound_id);
-       if (ma->ma_hsm.mh_arch_id != 0)
-               archive_id = ma->ma_hsm.mh_arch_id;
-       else
-               archive_id = cdt->cdt_default_archive_id;
-
-       hai.hai_fid = *mdt_object_fid(mo);
-
-       rc = mdt_agent_record_add(info->mti_env, info->mti_mdt,
-                                 compound_id, archive_id, 0, &hai);
-       if (rc)
-               CERROR("%s: unable to add HSM remove request for "DFID
-                      ": rc=%d\n", mdt_obd_name(info->mti_mdt),
-                      PFID(mdt_object_fid(mo)), rc);
+        }
+       repbody->mbo_eadatasize = 0;
 
         RETURN(0);
 }
@@ -999,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));
@@ -1019,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;
@@ -1208,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 =