Commit f696a3659fc4b3a3bf4bc83d9dbec5e5a2ffd929

Authored by Miklos Szeredi
Committed by Al Viro
1 parent 5cec56deb6

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

Showing 9 changed files with 30 additions and 44 deletions Side-by-side Diff

... ... @@ -275,9 +275,12 @@
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 */
... ... @@ -146,6 +146,9 @@
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))
... ... @@ -43,7 +43,7 @@
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,
... ... @@ -511,13 +511,6 @@
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))
... ... @@ -616,7 +609,6 @@
616 609 .lookup = hfs_file_lookup,
617 610 .truncate = hfs_file_truncate,
618 611 .setattr = hfs_inode_setattr,
619   - .permission = hfs_permission,
620 612 .setxattr = hfs_setxattr,
621 613 .getxattr = hfs_getxattr,
622 614 .listxattr = hfs_listxattr,
... ... @@ -238,18 +238,6 @@
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))
... ... @@ -281,7 +269,6 @@
281 269 static const struct inode_operations hfsplus_file_inode_operations = {
282 270 .lookup = hfsplus_file_lookup,
283 271 .truncate = hfsplus_file_truncate,
284   - .permission = hfsplus_permission,
285 272 .setxattr = hfsplus_setxattr,
286 273 .getxattr = hfsplus_getxattr,
287 274 .listxattr = hfsplus_listxattr,
... ... @@ -212,8 +212,7 @@
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  
220 219  
221 220  
... ... @@ -249,23 +248,11 @@
249 248 }
250 249  
251 250 /* Ordinary permission routines do not understand MAY_APPEND. */
252   - if (inode->i_op && inode->i_op->permission) {
  251 + if (inode->i_op && inode->i_op->permission)
253 252 retval = inode->i_op->permission(inode, mask);
254   - if (!retval) {
255   - /*
256   - * Exec permission on a regular file is denied if none
257   - * of the execute bits are set.
258   - *
259   - * This check should be done by the ->permission()
260   - * method.
261   - */
262   - if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
263   - !(inode->i_mode & S_IXUGO))
264   - return -EACCES;
265   - }
266   - } else {
  253 + else
267 254 retval = generic_permission(inode, mask, NULL);
268   - }
  255 +
269 256 if (retval)
270 257 return retval;
271 258  
... ... @@ -1957,6 +1957,9 @@
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;
fs/proc/proc_sysctl.c
... ... @@ -298,13 +298,19 @@
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 */
... ... @@ -1851,6 +1851,11 @@
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)