From: Andreas Gruenbacher <agruen@suse.de>

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 & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->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 & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->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 & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->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 & (MAY_READ|MAY_WRITE)) || (inode->i_mode & S_IXUGO))
+	if (!(mask & MAY_EXEC) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->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 & (S_IRUSR|S_IWUSR)) || (inode->i_mode & S_IXUGO))
+	if (!(orgmode & S_IXUSR) || (inode->i_mode & S_IXUGO) ||
+	    (ip->i_d.di_mode & S_IFMT) == S_IFDIR)
 		if (capable_cred(cr, CAP_DAC_OVERRIDE))
 			return 0;
 

_