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

From: Peter Backes (rtc@helen.PLASMA.Xg8.DE)
Date: Thu Jul 03 2003 - 11:51:29 EST


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


--- 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;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jul 07 2003 - 22:00:20 EST