<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Andreas Gruenbacher &lt;agruen@suse.de&gt;

The fix for permission() that makes it compliant with POSIX.1-2001
apparently was lost.  Here is the patch I sent before.  (The relevant lines
from the standard text are cited in
http://www.ussg.iu.edu/hypermail/linux/kernel/0310.2/0286.html.  The fix
proposed in that posting did not handle directories without execute
permissions correctly.)


Make permission check conform to POSIX.1-2001

The access(2) function does not conform to POSIX.1-2001: For root
and a file with no permissions, access(file, MAY_READ|MAY_EXEC)
returns 0 (it should return -1).



---

 fs/ext2/acl.c      |    3 ++-
 fs/ext3/acl.c      |    3 ++-
 fs/jfs/acl.c       |    3 ++-
 fs/namei.c         |    3 ++-
 fs/xfs/xfs_inode.c |    3 ++-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff -puN fs/ext2/acl.c~access-permissions-fix fs/ext2/acl.c
--- 25/fs/ext2/acl.c~access-permissions-fix	2004-02-01 13:04:41.000000000 -0800
+++ 25-akpm/fs/ext2/acl.c	2004-02-01 13:04:41.000000000 -0800
@@ -322,7 +322,8 @@ check_groups:
 
 check_capabilities:
 	/* Allowed to override Discretionary Access Control? */
-	if ((mask &amp; (MAY_READ|MAY_WRITE)) || (inode-&gt;i_mode &amp; S_IXUGO))
+	if (!(mask &amp; MAY_EXEC) ||
+	    (inode-&gt;i_mode &amp; S_IXUGO) || S_ISDIR(inode-&gt;i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
diff -puN fs/ext3/acl.c~access-permissions-fix fs/ext3/acl.c
--- 25/fs/ext3/acl.c~access-permissions-fix	2004-02-01 13:04:41.000000000 -0800
+++ 25-akpm/fs/ext3/acl.c	2004-02-01 13:04:41.000000000 -0800
@@ -327,7 +327,8 @@ check_groups:
 
 check_capabilities:
 	/* Allowed to override Discretionary Access Control? */
-	if ((mask &amp; (MAY_READ|MAY_WRITE)) || (inode-&gt;i_mode &amp; S_IXUGO))
+	if (!(mask &amp; MAY_EXEC) ||
+	    (inode-&gt;i_mode &amp; S_IXUGO) || S_ISDIR(inode-&gt;i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 	/* Read and search granted if capable(CAP_DAC_READ_SEARCH) */
diff -puN fs/jfs/acl.c~access-permissions-fix fs/jfs/acl.c
--- 25/fs/jfs/acl.c~access-permissions-fix	2004-02-01 13:04:41.000000000 -0800
+++ 25-akpm/fs/jfs/acl.c	2004-02-01 13:04:41.000000000 -0800
@@ -191,7 +191,8 @@ check_capabilities:
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((mask &amp; (MAY_READ|MAY_WRITE)) || (inode-&gt;i_mode &amp; S_IXUGO))
+	if (!(mask &amp; MAY_EXEC) ||
+	    (inode-&gt;i_mode &amp; S_IXUGO) || S_ISDIR(inode-&gt;i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 
diff -puN fs/namei.c~access-permissions-fix fs/namei.c
--- 25/fs/namei.c~access-permissions-fix	2004-02-01 13:04:41.000000000 -0800
+++ 25-akpm/fs/namei.c	2004-02-01 13:04:41.000000000 -0800
@@ -190,7 +190,8 @@ int vfs_permission(struct inode * inode,
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((mask &amp; (MAY_READ|MAY_WRITE)) || (inode-&gt;i_mode &amp; S_IXUGO))
+	if (!(mask &amp; MAY_EXEC) ||
+	    (inode-&gt;i_mode &amp; S_IXUGO) || S_ISDIR(inode-&gt;i_mode))
 		if (capable(CAP_DAC_OVERRIDE))
 			return 0;
 
diff -puN fs/xfs/xfs_inode.c~access-permissions-fix fs/xfs/xfs_inode.c
--- 25/fs/xfs/xfs_inode.c~access-permissions-fix	2004-02-01 13:04:41.000000000 -0800
+++ 25-akpm/fs/xfs/xfs_inode.c	2004-02-01 13:04:41.000000000 -0800
@@ -3707,7 +3707,8 @@ xfs_iaccess(
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((orgmode &amp; (S_IRUSR|S_IWUSR)) || (inode-&gt;i_mode &amp; S_IXUGO))
+	if (!(orgmode &amp; S_IXUSR) || (inode-&gt;i_mode &amp; S_IXUGO) ||
+	    (ip-&gt;i_d.di_mode &amp; S_IFMT) == S_IFDIR)
 		if (capable_cred(cr, CAP_DAC_OVERRIDE))
 			return 0;
 

_
</pre></body></html>