Whamcloud - gitweb
LU-6528 mdt: keep FS capability for intent_getattr 78/14978/3
authorLai Siyao <lai.siyao@intel.com>
Fri, 29 May 2015 01:59:45 +0000 (09:59 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 6 Jun 2015 13:52:08 +0000 (13:52 +0000)
When "no_subtree_check" is set for NFS export, nfsd_set_fh_dentry()
doesn't set correct fsuid explicitely, but raise capability to allow
exportfs_decode_fh() to reconnect disconnected dentry into dcache.
So for lookup (i.e. intent_getattr), we should keep FS capability on
MDS, otherwise it will fail permission check.

Signed-off-by: Lai Siyao <lai.siyao@intel.com>
Change-Id: I99e2caeec06239a1df39918cbd6e9213e37ec758
Reviewed-on: http://review.whamcloud.com/14978
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdd/mdd_permission.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c

index 750df8d..f082d41 100644 (file)
@@ -298,6 +298,9 @@ check_capabilities:
                if (md_capable(uc, CFS_CAP_DAC_READ_SEARCH))
                        RETURN(0);
 
+       CDEBUG(D_SEC, "permission denied, mode %x, fsuid %u, uid %u\n",
+              la->la_mode, uc->uc_fsuid, la->la_uid);
+
        RETURN(-EACCES);
 }
 
index a2cc964..381f056 100644 (file)
@@ -3123,9 +3123,9 @@ static int mdt_intent_getattr(enum mdt_it_code opcode,
                 GOTO(out_shrink, rc = -EINVAL);
         }
 
-        rc = mdt_init_ucred(info, reqbody);
-        if (rc)
-                GOTO(out_shrink, rc);
+       rc = mdt_init_ucred_intent_getattr(info, reqbody);
+       if (rc)
+               GOTO(out_shrink, rc);
 
         ldlm_rep = req_capsule_server_get(info->mti_pill, &RMF_DLM_REP);
         mdt_set_disposition(info, ldlm_rep, DISP_IT_EXECD);
index 61816a0..042bc50 100644 (file)
@@ -707,6 +707,7 @@ void mdt_dump_lmv(unsigned int level, const union lmv_mds_md *lmv);
 bool allow_client_chgrp(struct mdt_thread_info *info, struct lu_ucred *uc);
 int mdt_check_ucred(struct mdt_thread_info *);
 int mdt_init_ucred(struct mdt_thread_info *, struct mdt_body *);
+int mdt_init_ucred_intent_getattr(struct mdt_thread_info *, struct mdt_body *);
 int mdt_init_ucred_reint(struct mdt_thread_info *);
 void mdt_exit_ucred(struct mdt_thread_info *);
 int mdt_version_get_check(struct mdt_thread_info *, struct mdt_object *, int);
index a5cc692..984cfa2 100644 (file)
@@ -141,7 +141,7 @@ static void ucred_set_jobid(struct mdt_thread_info *info, struct lu_ucred *uc)
 }
 
 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
-                          void *buf)
+                         void *buf, bool drop_fs_cap)
 {
         struct ptlrpc_request   *req = mdt_info_req(info);
         struct mdt_device       *mdt = info->mti_mdt;
@@ -294,7 +294,7 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
        mdt_root_squash(info, peernid);
 
        /* remove fs privilege for non-root user. */
-       if (ucred->uc_fsuid)
+       if (ucred->uc_fsuid && drop_fs_cap)
                ucred->uc_cap = pud->pud_cap & ~CFS_CAP_FS_MASK;
        else
                ucred->uc_cap = pud->pud_cap;
@@ -477,7 +477,7 @@ static void mdt_squash_nodemap_id(struct lu_ucred *ucred,
 
 
 static int old_init_ucred(struct mdt_thread_info *info,
-                         struct mdt_body *body)
+                         struct mdt_body *body, bool drop_fs_cap)
 {
        struct lu_ucred         *uc = mdt_ucred(info);
        struct mdt_device       *mdt = info->mti_mdt;
@@ -525,7 +525,7 @@ static int old_init_ucred(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 = body->mbo_capability & ~CFS_CAP_FS_MASK;
        else
                uc->uc_cap = body->mbo_capability;
@@ -583,38 +583,56 @@ static int old_init_ucred_reint(struct mdt_thread_info *info)
        RETURN(0);
 }
 
-int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
+static inline int __mdt_init_ucred(struct mdt_thread_info *info,
+                                  struct mdt_body *body,
+                                  bool drop_fs_cap)
 {
-        struct ptlrpc_request *req = mdt_info_req(info);
-       struct lu_ucred       *uc  = mdt_ucred(info);
+       struct ptlrpc_request   *req = mdt_info_req(info);
+       struct lu_ucred         *uc  = mdt_ucred(info);
 
        LASSERT(uc != NULL);
        if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW))
                return 0;
 
-        mdt_exit_ucred(info);
+       mdt_exit_ucred(info);
 
-        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
-                return old_init_ucred(info, body);
-        else
-                return new_init_ucred(info, BODY_INIT, body);
+       if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
+               return old_init_ucred(info, body, drop_fs_cap);
+       else
+               return new_init_ucred(info, BODY_INIT, body, drop_fs_cap);
+}
+
+int mdt_init_ucred(struct mdt_thread_info *info, struct mdt_body *body)
+{
+       return __mdt_init_ucred(info, body, true);
+}
+
+/* LU-6528 when "no_subtree_check" is set for NFS export, nfsd_set_fh_dentry()
+ * doesn't set correct fsuid explicitely, but raise capability to allow
+ * exportfs_decode_fh() to reconnect disconnected dentry into dcache. So for
+ * lookup (i.e. intent_getattr), we should keep FS capability, otherwise it
+ * will fail permission check. */
+int mdt_init_ucred_intent_getattr(struct mdt_thread_info *info,
+                                 struct mdt_body *body)
+{
+       return __mdt_init_ucred(info, body, false);
 }
 
 int mdt_init_ucred_reint(struct mdt_thread_info *info)
 {
-        struct ptlrpc_request *req = mdt_info_req(info);
+       struct ptlrpc_request *req = mdt_info_req(info);
        struct lu_ucred       *uc  = mdt_ucred(info);
 
        LASSERT(uc != NULL);
        if ((uc->uc_valid == UCRED_OLD) || (uc->uc_valid == UCRED_NEW))
                return 0;
 
-        mdt_exit_ucred(info);
+       mdt_exit_ucred(info);
 
-        if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
-                return old_init_ucred_reint(info);
-        else
-                return new_init_ucred(info, REC_INIT, NULL);
+       if (!req->rq_auth_gss || req->rq_auth_usr_mdt || !req->rq_user_desc)
+               return old_init_ucred_reint(info);
+       else
+               return new_init_ucred(info, REC_INIT, NULL, true);
 }
 
 /* copied from lov/lov_ea.c, just for debugging, will be removed later */