Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] move executable checking into ->permission()

For execute permission on a regular files we need to check if file has
any execute bits at all, regardless of capabilites.

This check is normally performed by generic_permission() but was also
added to the case when the filesystem defines its own ->permission()
method. In the latter case the filesystem should be responsible for
performing this check.

Move the check from inode_permission() inside filesystems which are
not calling generic_permission().

Create a helper function execute_ok() that returns true if the inode
is a directory or if any execute bits are present in i_mode.

Also fix up the following code:

- coda control file is never executable
- sysctl files are never executable
- hfs_permission seems broken on MAY_EXEC, remove
- hfsplus_permission is eqivalent to generic_permission(), remove

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>

authored by

Miklos Szeredi and committed by
Al Viro
f696a365 5cec56de

+30 -44
+6 -3
fs/cifs/cifsfs.c
··· 275 275 276 276 cifs_sb = CIFS_SB(inode->i_sb); 277 277 278 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) 279 - return 0; 280 - else /* file mode might have been restricted at mount time 278 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { 279 + if ((mask & MAY_EXEC) && !execute_ok(inode)) 280 + return -EACCES; 281 + else 282 + return 0; 283 + } else /* file mode might have been restricted at mount time 281 284 on the client (above and beyond ACL on servers) for 282 285 servers which do not support setting and viewing mode bits, 283 286 so allowing client to check permissions is useful */
+3
fs/coda/dir.c
··· 146 146 if (!mask) 147 147 return 0; 148 148 149 + if ((mask & MAY_EXEC) && !execute_ok(inode)) 150 + return -EACCES; 151 + 149 152 lock_kernel(); 150 153 151 154 if (coda_cache_check(inode, mask))
+1 -1
fs/coda/pioctl.c
··· 43 43 /* the coda pioctl inode ops */ 44 44 static int coda_ioctl_permission(struct inode *inode, int mask) 45 45 { 46 - return 0; 46 + return (mask & MAY_EXEC) ? -EACCES : 0; 47 47 } 48 48 49 49 static int coda_pioctl(struct inode * inode, struct file * filp,
-8
fs/hfs/inode.c
··· 511 511 } 512 512 } 513 513 514 - static int hfs_permission(struct inode *inode, int mask) 515 - { 516 - if (S_ISREG(inode->i_mode) && mask & MAY_EXEC) 517 - return 0; 518 - return generic_permission(inode, mask, NULL); 519 - } 520 - 521 514 static int hfs_file_open(struct inode *inode, struct file *file) 522 515 { 523 516 if (HFS_IS_RSRC(inode)) ··· 609 616 .lookup = hfs_file_lookup, 610 617 .truncate = hfs_file_truncate, 611 618 .setattr = hfs_inode_setattr, 612 - .permission = hfs_permission, 613 619 .setxattr = hfs_setxattr, 614 620 .getxattr = hfs_getxattr, 615 621 .listxattr = hfs_listxattr,
-13
fs/hfsplus/inode.c
··· 238 238 perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); 239 239 } 240 240 241 - static int hfsplus_permission(struct inode *inode, int mask) 242 - { 243 - /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup, 244 - * open_exec has the same test, so it's still not executable, if a x bit 245 - * is set fall back to standard permission check. 246 - */ 247 - if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111)) 248 - return 0; 249 - return generic_permission(inode, mask, NULL); 250 - } 251 - 252 - 253 241 static int hfsplus_file_open(struct inode *inode, struct file *file) 254 242 { 255 243 if (HFSPLUS_IS_RSRC(inode)) ··· 269 281 static const struct inode_operations hfsplus_file_inode_operations = { 270 282 .lookup = hfsplus_file_lookup, 271 283 .truncate = hfsplus_file_truncate, 272 - .permission = hfsplus_permission, 273 284 .setxattr = hfsplus_setxattr, 274 285 .getxattr = hfsplus_getxattr, 275 286 .listxattr = hfsplus_listxattr,
+4 -17
fs/namei.c
··· 212 212 * Read/write DACs are always overridable. 213 213 * Executable DACs are overridable if at least one exec bit is set. 214 214 */ 215 - if (!(mask & MAY_EXEC) || 216 - (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode)) 215 + if (!(mask & MAY_EXEC) || execute_ok(inode)) 217 216 if (capable(CAP_DAC_OVERRIDE)) 218 217 return 0; 219 218 ··· 248 249 } 249 250 250 251 /* Ordinary permission routines do not understand MAY_APPEND. */ 251 - if (inode->i_op && inode->i_op->permission) { 252 + if (inode->i_op && inode->i_op->permission) 252 253 retval = inode->i_op->permission(inode, mask); 253 - if (!retval) { 254 - /* 255 - * Exec permission on a regular file is denied if none 256 - * of the execute bits are set. 257 - * 258 - * This check should be done by the ->permission() 259 - * method. 260 - */ 261 - if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) && 262 - !(inode->i_mode & S_IXUGO)) 263 - return -EACCES; 264 - } 265 - } else { 254 + else 266 255 retval = generic_permission(inode, mask, NULL); 267 - } 256 + 268 257 if (retval) 269 258 return retval; 270 259
+3
fs/nfs/dir.c
··· 1957 1957 } else 1958 1958 res = PTR_ERR(cred); 1959 1959 out: 1960 + if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) 1961 + res = -EACCES; 1962 + 1960 1963 dfprintk(VFS, "NFS: permission(%s/%ld), mask=0x%x, res=%d\n", 1961 1964 inode->i_sb->s_id, inode->i_ino, mask, res); 1962 1965 return res;
+8 -2
fs/proc/proc_sysctl.c
··· 298 298 * sysctl entries that are not writeable, 299 299 * are _NOT_ writeable, capabilities or not. 300 300 */ 301 - struct ctl_table_header *head = grab_header(inode); 302 - struct ctl_table *table = PROC_I(inode)->sysctl_entry; 301 + struct ctl_table_header *head; 302 + struct ctl_table *table; 303 303 int error; 304 304 305 + /* Executable files are not allowed under /proc/sys/ */ 306 + if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) 307 + return -EACCES; 308 + 309 + head = grab_header(inode); 305 310 if (IS_ERR(head)) 306 311 return PTR_ERR(head); 307 312 313 + table = PROC_I(inode)->sysctl_entry; 308 314 if (!table) /* global root - r-xr-xr-x */ 309 315 error = mask & MAY_WRITE ? -EACCES : 0; 310 316 else /* Use the permissions on the sysctl table entry */
+5
include/linux/fs.h
··· 1851 1851 extern int generic_permission(struct inode *, int, 1852 1852 int (*check_acl)(struct inode *, int)); 1853 1853 1854 + static inline bool execute_ok(struct inode *inode) 1855 + { 1856 + return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); 1857 + } 1858 + 1854 1859 extern int get_write_access(struct inode *); 1855 1860 extern int deny_write_access(struct file *); 1856 1861 static inline void put_write_access(struct inode * inode)