fix permission checks for executables
PATCH 1/1 fix permission checks for executables
Hi Linux,
vfs_permission in the Linux 2.4 series tries to check for CAP_DAC_OVERRIDE if the modes didn't match. This means even for an file without executable bits set at all, root will
be reported that it is. I've actually found one apllication
(scomail under linux-abi) that fails because of this, besides not matching my reading of Posix 1003.1e.
Of the operating systems with capabilty-like features at least OpenUNIX gets it right, of the others at least OpenServer and 4.4BSD, but these semantics seem natural to me anyway..
Please aplly the attached patch.
Christoph
Signature · 20 lines
Whip me. Beat me. Make me maintain AIX. --- linux.really_plain/fs/namei.c Wed Aug 8 17:56:58 2001 +++ linux.plain/fs/namei.c Wed Aug 8 18:13:22 2001 @@ -163,9 +163,13 @@ else if (in_group_p(inode->i_gid)) mode >>= 3; - if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE)) + if (((mode & mask & S_IRWXO) == mask)) return 0; + if (!(mask & S_IXOTH) || S_ISDIR(inode->i_mode)) + if (capable(CAP_DAC_OVERRIDE)) + return 0; + /* read and search access */ if ((mask == S_IROTH) || (S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))
Quoted 9 lines · Christoph Hellwig
Hi Linux,
vfs_permissionin the Linux 2.4 series tries to check forCAP_DAC_OVERRIDEif the modes didn't match. This means even for an file without executable bits set at all, root will
be reported that it is. I've actually found one apllication
(scomail under linux-abi) that fails because of this, besides not matching my reading of Posix 1003.1e.
Quoted 3 lines
Of the operating systems with capabilty-like features at least OpenUNIX gets it right, of the others at least OpenServer and 4.4BSD, but these semantics seem natural to me anyway..
Andreas Gruenbacher pointed out that it is much leaner to use MAY_READ¸MAY_EXEC and MAY_WRITE instead of abusing the stat-macros.
Here is a patch that changes the complete function to use these and also cleans up and clarifies the comments.
Christoph
fs/namei.c +27 -11
@@ -140,7 +140,7 @@ }/* -* permission() +* vfs_permission() * * is used to check for read/write/execute permissions on a file. * We use "fsuid" for this, letting us set arbitrary permissions
@@ -151,24 +151,40 @@ {int mode = inode->i_mode; -if ((mask &S_IWOTH ) &&IS_RDONLY (inode) && - (S_ISREG (mode) ||S_ISDIR (mode) ||S_ISLNK (mode))) -return -EROFS ;/* Nobody gets write access to a read-only fs */ - -if ((mask &S_IWOTH ) &&IS_IMMUTABLE (inode)) -return -EACCES ;/* Nobody gets write access to an immutable file */ +if (mask &MAY_WRITE ) { +/* +* Nobody gets write access to a read-only fs. +*/ +if (IS_RDONLY (inode) && + (S_ISREG (mode) ||S_ISDIR (mode) ||S_ISLNK (mode))) +return -EROFS ; + +/* +* Nobody gets write access to an immutable file. +*/ +if (IS_IMMUTABLE (inode)) +return -EACCES ; + }if (current->fsuid == inode->i_uid) mode >>=6 ;else if (in_group_p (inode->i_gid)) mode >>=3 ; -if (((mode & mask &S_IRWXO ) == mask) ||capable (CAP_DAC_OVERRIDE )) +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 )))) +/* +* Only read/write DACs are overridable. +*/ +if ((mask & (MAY_READ |MAY_WRITE )) ||S_ISDIR (inode->i_mode)) +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 ;