make exec_permission(dir) really equivalent to inode_permission(dir, MAY_EXEC)
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 19 Jun 2011 05:50:08 +0000 (01:50 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 20 Jul 2011 05:43:05 +0000 (01:43 -0400)
capability overrides apply only to the default case; if fs has ->permission()
that does _not_ call generic_permission(), we have no business doing them.
Moreover, if it has ->permission() that does call generic_permission(), we
have no need to recheck capabilities.

Besides, the capability overrides should apply only if we got EACCES from
acl_permission_check(); any other value (-EIO, etc.) should be returned
to caller, capabilities or not capabilities.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index 5ba42c4..7c8a930 100644 (file)
@@ -584,19 +584,19 @@ static inline int exec_permission(struct inode *inode, unsigned int flags)
 
        if (inode->i_op->permission) {
                ret = inode->i_op->permission(inode, MAY_EXEC, flags);
+               if (likely(!ret))
+                       goto ok;
        } else {
                ret = acl_permission_check(inode, MAY_EXEC, flags,
                                inode->i_op->check_acl);
+               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;
        }
-       if (likely(!ret))
-               goto ok;
-       if (ret == -ECHILD)
-               return ret;
-
-       if (ns_capable(ns, CAP_DAC_OVERRIDE) ||
-                       ns_capable(ns, CAP_DAC_READ_SEARCH))
-               goto ok;
-
        return ret;
 ok:
        return security_inode_exec_permission(inode, flags);