Whamcloud - gitweb
LU-3727 nfs: Fix ll_get_parent() LBUG caused by permission 27/7327/13
authorLi Xi <lixi@ddn.com>
Wed, 8 Oct 2014 12:27:22 +0000 (20:27 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 26 Dec 2014 16:57:20 +0000 (16:57 +0000)
When ll_get_parent() is trying to get the attributes of parent
directory, EACCES will be returned if NFS daemon user does not
have the execute permission of the child directory. This patch
fixes the problem by skipping permission check for ll_get_parent().

Signed-off-by: Li Xi <lixi@ddn.com>
Change-Id: Id922d170c89519b755f69a2818d6ed53f8cc7ad9
Reviewed-on: http://review.whamcloud.com/7327
Reviewed-by: Bobi Jam <bobijam@gmail.com>
Tested-by: Jenkins
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/md_object.h
lustre/mdd/mdd_dir.c
lustre/mdt/mdt_handler.c

index 12c224c..99998e2 100644 (file)
@@ -161,7 +161,8 @@ struct md_op_spec {
        /** don't create lov objects or llog cookie - this replay */
        unsigned int no_create:1,
                     sp_cr_lookup:1, /* do lookup sanity check or not. */
-                    sp_rm_entry:1;  /* only remove name entry */
+                    sp_rm_entry:1,  /* only remove name entry */
+                    sp_permitted:1; /* do not check permission */
 
        /** Current lock mode for parent dir where create is performing. */
         mdl_mode_t sp_cr_mode;
index 9744718..5d4fbf3 100644 (file)
@@ -119,7 +119,8 @@ int mdd_lookup(const struct lu_env *env,
        if (rc != 0)
                RETURN(rc);
 
-       rc = __mdd_lookup(env, pobj, pattr, lname, fid, MAY_EXEC);
+       rc = __mdd_lookup(env, pobj, pattr, lname, fid,
+                         (spec != NULL && spec->sp_permitted) ? 0 : MAY_EXEC);
         RETURN(rc);
 }
 
index 619fa79..79ca02b 100644 (file)
@@ -1309,43 +1309,32 @@ out:
 }
 
 static int mdt_raw_lookup(struct mdt_thread_info *info,
-                          struct mdt_object *parent,
-                          const struct lu_name *lname,
-                          struct ldlm_reply *ldlm_rep)
+                         struct mdt_object *parent,
+                         const struct lu_name *lname,
+                         struct ldlm_reply *ldlm_rep)
 {
-        struct md_object *next = mdt_object_child(info->mti_object);
-        const struct mdt_body *reqbody = info->mti_body;
-        struct lu_fid *child_fid = &info->mti_tmp_fid1;
-        struct mdt_body *repbody;
-        int rc;
-        ENTRY;
-
-       if (reqbody->mbo_valid != OBD_MD_FLID)
-                RETURN(0);
+       struct lu_fid   *child_fid = &info->mti_tmp_fid1;
+       int              rc;
+       ENTRY;
 
-        LASSERT(!info->mti_cross_ref);
+       LASSERT(!info->mti_cross_ref);
 
-        /* Only got the fid of this obj by name */
-        fid_zero(child_fid);
-        rc = mdo_lookup(info->mti_env, next, lname, child_fid,
-                        &info->mti_spec);
-#if 0
-        /* XXX is raw_lookup possible as intent operation? */
-        if (rc != 0) {
-                if (rc == -ENOENT)
-                        mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
-                RETURN(rc);
-        } else
-                mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
+       /* Only got the fid of this obj by name */
+       fid_zero(child_fid);
+       rc = mdo_lookup(info->mti_env, mdt_object_child(info->mti_object),
+                       lname, child_fid, &info->mti_spec);
+       if (rc == 0) {
+               struct mdt_body *repbody;
 
-        repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
-#endif
-        if (rc == 0) {
-                repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
+               repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY);
                repbody->mbo_fid1 = *child_fid;
                repbody->mbo_valid = OBD_MD_FLID;
-        }
-        RETURN(1);
+               mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_POS);
+       } else if (rc == -ENOENT) {
+               mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
+       }
+
+       RETURN(rc);
 }
 
 /*
@@ -1467,10 +1456,15 @@ static int mdt_getattr_name_lock(struct mdt_thread_info *info,
        }
 
        if (lu_name_is_valid(lname)) {
-               rc = mdt_raw_lookup(info, parent, lname, ldlm_rep);
-               if (rc != 0) {
-                       if (rc > 0)
-                               rc = 0;
+               /* Always allow to lookup ".." */
+               if (unlikely(lname->ln_namelen == 2 &&
+                            lname->ln_name[0] == '.' &&
+                            lname->ln_name[1] == '.'))
+                       info->mti_spec.sp_permitted = 1;
+
+               if (info->mti_body->mbo_valid == OBD_MD_FLID) {
+                       rc = mdt_raw_lookup(info, parent, lname, ldlm_rep);
+
                        RETURN(rc);
                }
 
@@ -2875,6 +2869,7 @@ void mdt_thread_info_init(struct ptlrpc_request *req,
 
         info->mti_spec.no_create = 0;
        info->mti_spec.sp_rm_entry = 0;
+       info->mti_spec.sp_permitted = 0;
 
        info->mti_spec.u.sp_ea.eadata = NULL;
        info->mti_spec.u.sp_ea.eadatalen = 0;