merge do_revalidate() into its only caller
[pandora-kernel.git] / fs / namei.c
index 21eba95..42ccb97 100644 (file)
@@ -235,12 +235,21 @@ int generic_permission(struct inode *inode, int mask)
        if (ret != -EACCES)
                return ret;
 
+       if (S_ISDIR(inode->i_mode)) {
+               /* DACs are overridable for directories */
+               if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
+                       return 0;
+               if (!(mask & MAY_WRITE))
+                       if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
+                               return 0;
+               return -EACCES;
+       }
        /*
         * Read/write DACs are always overridable.
-        * Executable DACs are overridable for all directories and
-        * for non-directories that have least one exec bit set.
+        * Executable DACs are overridable when there is
+        * at least one exec bit set.
         */
-       if (!(mask & MAY_EXEC) || execute_ok(inode))
+       if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
                if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
                        return 0;
 
@@ -248,7 +257,7 @@ int generic_permission(struct inode *inode, int mask)
         * Searching includes executable on directories, else just read.
         */
        mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
-       if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
+       if (mask == MAY_READ)
                if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH))
                        return 0;
 
@@ -301,43 +310,6 @@ int inode_permission(struct inode *inode, int mask)
        return security_inode_permission(inode, mask);
 }
 
-/**
- * exec_permission  -  check for right to do lookups in a given directory
- * @inode:     inode to check permission on
- * @mask:      MAY_EXEC and possibly MAY_NOT_BLOCK flags.
- *
- * Short-cut version of inode_permission(), for calling on directories
- * during pathname resolution.  Combines parts of inode_permission()
- * and generic_permission(), and tests ONLY for MAY_EXEC permission.
- *
- * If appropriate, check DAC only.  If not appropriate, or
- * short-cut DAC fails, then call ->permission() to do more
- * complete permission check.
- */
-static inline int exec_permission(struct inode *inode, int mask)
-{
-       int ret;
-       struct user_namespace *ns = inode_userns(inode);
-
-       if (inode->i_op->permission) {
-               ret = inode->i_op->permission(inode, mask);
-               if (likely(!ret))
-                       goto ok;
-       } else {
-               ret = acl_permission_check(inode, mask);
-               if (likely(!ret))
-                       goto ok;
-               if (ret != -EACCES)
-                       return ret;
-               if (ns_capable(ns, CAP_DAC_OVERRIDE) ||
-                               ns_capable(ns, CAP_DAC_READ_SEARCH))
-                       goto ok;
-       }
-       return ret;
-ok:
-       return security_inode_permission(inode, mask);
-}
-
 /**
  * path_get - get a reference to a path
  * @path: path to get the reference to
@@ -464,28 +436,6 @@ static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
        return dentry->d_op->d_revalidate(dentry, nd);
 }
 
-static struct dentry *
-do_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-       int status = d_revalidate(dentry, nd);
-       if (unlikely(status <= 0)) {
-               /*
-                * The dentry failed validation.
-                * If d_revalidate returned 0 attempt to invalidate
-                * the dentry otherwise d_revalidate is asking us
-                * to return a fail status.
-                */
-               if (status < 0) {
-                       dput(dentry);
-                       dentry = ERR_PTR(status);
-               } else if (!d_invalidate(dentry)) {
-                       dput(dentry);
-                       dentry = NULL;
-               }
-       }
-       return dentry;
-}
-
 /**
  * complete_walk - successful completion of path walk
  * @nd:  pointer nameidata
@@ -1211,13 +1161,13 @@ retry:
 static inline int may_lookup(struct nameidata *nd)
 {
        if (nd->flags & LOOKUP_RCU) {
-               int err = exec_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
+               int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
                if (err != -ECHILD)
                        return err;
                if (unlazy_walk(nd, NULL))
                        return -ECHILD;
        }
-       return exec_permission(nd->inode, MAY_EXEC);
+       return inode_permission(nd->inode, MAY_EXEC);
 }
 
 static inline int handle_dots(struct nameidata *nd, int type)
@@ -1492,7 +1442,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        if (!S_ISDIR(dentry->d_inode->i_mode))
                                goto fput_fail;
 
-                       retval = exec_permission(dentry->d_inode, MAY_EXEC);
+                       retval = inode_permission(dentry->d_inode, MAY_EXEC);
                        if (retval)
                                goto fput_fail;
                }
@@ -1649,7 +1599,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
        struct dentry *dentry;
        int err;
 
-       err = exec_permission(inode, MAY_EXEC);
+       err = inode_permission(inode, MAY_EXEC);
        if (err)
                return ERR_PTR(err);
 
@@ -1670,8 +1620,24 @@ static struct dentry *__lookup_hash(struct qstr *name,
                        return dentry;
        }
 
-       if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE))
-               dentry = do_revalidate(dentry, nd);
+       if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) {
+               int status = d_revalidate(dentry, nd);
+               if (unlikely(status <= 0)) {
+                       /*
+                        * The dentry failed validation.
+                        * If d_revalidate returned 0 attempt to invalidate
+                        * the dentry otherwise d_revalidate is asking us
+                        * to return a fail status.
+                        */
+                       if (status < 0) {
+                               dput(dentry);
+                               return ERR_PTR(status);
+                       } else if (!d_invalidate(dentry)) {
+                               dput(dentry);
+                               dentry = NULL;
+                       }
+               }
+       }
 
        if (!dentry)
                dentry = d_alloc_and_lookup(base, name, nd);