PATCH (2.2): Fix for misbehaving access(x, X_OK)

Peter Backes
2003-07-03T16:40:52Z

[-- Attachment #1: Mail message body --]
[-- Type: text/plain, Size: 671 bytes --]

Hi,

here is a patch for the quirk in 2.2 kernels I reported yesterday. I
mostly took the changes from 2.4.9 to 2.4.10, see
http://lists.insecure.org/lists/linux-kernel/2001/Sep/0152.html,
and applied them to 2.2.25. Thus it is based on the patch by
Christoph Hellwig.

Keywords:
access() system call, X_OK, sys_access(), permission(),
vfs_permission(), execute, x-bit, root, uid 0, bash, test -x,
/usr/bin/access -x, CAP_DAC_OVERRIDE,
/usr/lib/rpm/find-requires: /usr/lib/rpm/perl.req: /usr/bin/perl: bad interpreter: Permission denied

Please make sure you CC me if you reply as I'm not subscribed.

-- Peter 'Rattacresh' Backes, rtc@helen.PLASMA.Xg8.DE

[-- Attachment #2: Text from file 'linux-2.2.24-permbug.patch' --]
[-- Type: text/plain, Size: 4025 bytes --]

--- linux/fs/namei.c.old Fri Nov 2 17:38:46 2001
+++ linux/fs/namei.c Thu Jul 3 02:25:52 2003
@@ -149,11 +149,23 @@
mode >>= 6;
else if (in_group_p(inode->i_gid))
mode >>= 3;
- if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
+ /*
+ * If the DACs are ok we don't need any capability check.
+ */
+ if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
return 0;
- /* read and search access */
- if ((mask == S_IROTH) ||
- (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))
+ /*
+ * 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 (capable(CAP_DAC_OVERRIDE))
+ return 0;
+
+ /*
+ * Searching includes executable on directories, else just read.
+ */
+ if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
if (capable(CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
--- linux/fs/ext2/acl.c.old Sun Mar 25 18:30:36 2001
+++ linux/fs/ext2/acl.c Thu Jul 3 03:41:10 2003
@@ -51,10 +51,23 @@
* Access is always granted for root. We now check last,
* though, for BSD process accounting correctness
*/
- if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
+ /*
+ * If the DACs are ok we don't need any capability check.
+ */
+ if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
return 0;
- if ((mask == S_IROTH) ||
- (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))
+ /*
+ * 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 (capable(CAP_DAC_OVERRIDE))
+ return 0;
+
+ /*
+ * Searching includes executable on directories, else just read.
+ */
+ if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
if (capable(CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
--- linux/fs/ufs/acl.c.old Sun Mar 25 18:30:37 2001
+++ linux/fs/ufs/acl.c Thu Jul 3 03:45:39 2003
@@ -58,10 +58,23 @@
* Access is always granted for root. We now check last,
* though, for BSD process accounting correctness
*/
- if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
+ /*
+ * If the DACs are ok we don't need any capability check.
+ */
+ if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
return 0;
- if ((mask == S_IROTH) ||
- (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))
+ /*
+ * 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 (capable(CAP_DAC_OVERRIDE))
+ return 0;
+
+ /*
+ * Searching includes executable on directories, else just read.
+ */
+ if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
if (capable(CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
--- linux/fs/proc/inode.c.old Sun Mar 25 18:30:36 2001
+++ linux/fs/proc/inode.c Thu Jul 3 03:43:56 2003
@@ -145,11 +145,23 @@
mode >>= 6;
else if (in_group_p(inode->i_gid))
mode >>= 3;
- if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
+ /*
+ * If the DACs are ok we don't need any capability check.
+ */
+ if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
return 0;
- /* read and search access */
- if ((mask == S_IROTH) ||
- (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))
+ /*
+ * 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 (capable(CAP_DAC_OVERRIDE))
+ return 0;
+
+ /*
+ * Searching includes executable on directories, else just read.
+ */
+ if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
if (capable(CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;