Messages in this thread Patch in this message | | | Date | Thu, 13 Jul 2000 08:47:16 +0200 (CEST) | From | Wojciech Purczynski <> | Subject | Invalid checking of directory in *permission() |
| |
Hello,
I've found bug in *permission() functions that checks CAP_DAC_READ_SEARCH capability to access a directory. Those functions uses local variable named 'mode' which initialized on startup to inode->i_mode but later in the code its value may be shifted by 3 or 6 bits. Then it is used to check if current inode is a directory with S_ISDIR(mode) macro. This is invalid and should be S_ISDIR(inode->i_node).
If process has CAP_DAC_OVERRIDE cleared and CAP_DAC_READ_SEARCH raised it may cause security problems.
Problem exists in kernels up to 2.2.17pre10 (and probably 2.4.0).
I attached patch against 2.2.16 kernel but I haven't tested it.
Greets, -wp
PS: Please include me in CC as I'm not subscribed to the list.
+--------------------------------------------------------------------+ | Wojciech Purczynski wp@elzabsoft.pl http://www.elzabsoft.pl/~wp | | GSM: +48604432981 Linux Administrator SMS: wp-sms@elzabsoft.pl | +------ Public GnuPG Key: http://www.elzabsoft.pl/~wp/gpg.asc ------+ diff -u -r linux/fs/ext2/acl.c linux-perm/fs/ext2/acl.c --- linux/fs/ext2/acl.c Wed May 6 19:56:08 1998 +++ linux-perm/fs/ext2/acl.c Wed Jul 12 22:03:27 2000 @@ -54,7 +54,7 @@ if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) return 0; if ((mask == S_IROTH) || - (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) if (capable(CAP_DAC_READ_SEARCH)) return 0; return -EACCES; diff -u -r linux/fs/namei.c linux-perm/fs/namei.c --- linux/fs/namei.c Tue Jan 4 19:12:23 2000 +++ linux-perm/fs/namei.c Wed Jul 12 22:02:41 2000 @@ -155,7 +155,7 @@ return 0; /* read and search access */ if ((mask == S_IROTH) || - (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) if (capable(CAP_DAC_READ_SEARCH)) return 0; return -EACCES; diff -u -r linux/fs/proc/inode.c linux-perm/fs/proc/inode.c --- linux/fs/proc/inode.c Sat May 9 03:10:30 1998 +++ linux-perm/fs/proc/inode.c Wed Jul 12 22:03:36 2000 @@ -149,7 +149,7 @@ return 0; /* read and search access */ if ((mask == S_IROTH) || - (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) if (capable(CAP_DAC_READ_SEARCH)) return 0; return -EACCES; diff -u -r linux/fs/ufs/acl.c linux-perm/fs/ufs/acl.c --- linux/fs/ufs/acl.c Mon Jan 4 20:51:29 1999 +++ linux-perm/fs/ufs/acl.c Wed Jul 12 22:03:01 2000 @@ -61,7 +61,7 @@ if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) return 0; if ((mask == S_IROTH) || - (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH)))) + (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH)))) if (capable(CAP_DAC_READ_SEARCH)) return 0; return -EACCES;
| |