diff options
-rw-r--r-- | fs/exec.c | 4 | ||||
-rw-r--r-- | fs/inotify.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 23 | ||||
-rw-r--r-- | fs/namespace.c | 2 | ||||
-rw-r--r-- | fs/open.c | 12 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | net/unix/af_unix.c | 2 |
7 files changed, 31 insertions, 15 deletions
@@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
135 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) | 135 | if (!S_ISREG(nd.dentry->d_inode->i_mode)) |
136 | goto exit; | 136 | goto exit; |
137 | 137 | ||
138 | error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); | 138 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC); |
139 | if (error) | 139 | if (error) |
140 | goto exit; | 140 | goto exit; |
141 | 141 | ||
@@ -495,7 +495,7 @@ struct file *open_exec(const char *name) | |||
495 | file = ERR_PTR(-EACCES); | 495 | file = ERR_PTR(-EACCES); |
496 | if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && | 496 | if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && |
497 | S_ISREG(inode->i_mode)) { | 497 | S_ISREG(inode->i_mode)) { |
498 | int err = permission(inode, MAY_EXEC, &nd); | 498 | int err = vfs_permission(&nd, MAY_EXEC); |
499 | if (!err && !(inode->i_mode & 0111)) | 499 | if (!err && !(inode->i_mode & 0111)) |
500 | err = -EACCES; | 500 | err = -EACCES; |
501 | file = ERR_PTR(err); | 501 | file = ERR_PTR(err); |
diff --git a/fs/inotify.c b/fs/inotify.c index 9fbaebfdf40b..bf7ce1d2412b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) | |||
372 | if (error) | 372 | if (error) |
373 | return error; | 373 | return error; |
374 | /* you can only watch an inode if you have read permissions on it */ | 374 | /* you can only watch an inode if you have read permissions on it */ |
375 | error = permission(nd->dentry->d_inode, MAY_READ, NULL); | 375 | error = vfs_permission(nd, MAY_READ); |
376 | if (error) | 376 | if (error) |
377 | path_release(nd); | 377 | path_release(nd); |
378 | return error; | 378 | return error; |
diff --git a/fs/namei.c b/fs/namei.c index b3f8a1966c9c..25e4ab4ce8b7 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
256 | return security_inode_permission(inode, mask, nd); | 256 | return security_inode_permission(inode, mask, nd); |
257 | } | 257 | } |
258 | 258 | ||
259 | /** | ||
260 | * vfs_permission - check for access rights to a given path | ||
261 | * @nd: lookup result that describes the path | ||
262 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
263 | * | ||
264 | * Used to check for read/write/execute permissions on a path. | ||
265 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
266 | * for filesystem access without changing the "normal" uids which | ||
267 | * are used for other things. | ||
268 | */ | ||
269 | int vfs_permission(struct nameidata *nd, int mask) | ||
270 | { | ||
271 | return permission(nd->dentry->d_inode, mask, nd); | ||
272 | } | ||
273 | |||
259 | /* | 274 | /* |
260 | * get_write_access() gets write permission for a file. | 275 | * get_write_access() gets write permission for a file. |
261 | * put_write_access() releases this write permission. | 276 | * put_write_access() releases this write permission. |
@@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
765 | 780 | ||
766 | nd->flags |= LOOKUP_CONTINUE; | 781 | nd->flags |= LOOKUP_CONTINUE; |
767 | err = exec_permission_lite(inode, nd); | 782 | err = exec_permission_lite(inode, nd); |
768 | if (err == -EAGAIN) { | 783 | if (err == -EAGAIN) |
769 | err = permission(inode, MAY_EXEC, nd); | 784 | err = vfs_permission(nd, MAY_EXEC); |
770 | } | ||
771 | if (err) | 785 | if (err) |
772 | break; | 786 | break; |
773 | 787 | ||
@@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1407 | if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) | 1421 | if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) |
1408 | return -EISDIR; | 1422 | return -EISDIR; |
1409 | 1423 | ||
1410 | error = permission(inode, acc_mode, nd); | 1424 | error = vfs_permission(nd, acc_mode); |
1411 | if (error) | 1425 | if (error) |
1412 | return error; | 1426 | return error; |
1413 | 1427 | ||
@@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup); | |||
2536 | EXPORT_SYMBOL(path_release); | 2550 | EXPORT_SYMBOL(path_release); |
2537 | EXPORT_SYMBOL(path_walk); | 2551 | EXPORT_SYMBOL(path_walk); |
2538 | EXPORT_SYMBOL(permission); | 2552 | EXPORT_SYMBOL(permission); |
2553 | EXPORT_SYMBOL(vfs_permission); | ||
2539 | EXPORT_SYMBOL(unlock_rename); | 2554 | EXPORT_SYMBOL(unlock_rename); |
2540 | EXPORT_SYMBOL(vfs_create); | 2555 | EXPORT_SYMBOL(vfs_create); |
2541 | EXPORT_SYMBOL(vfs_follow_link); | 2556 | EXPORT_SYMBOL(vfs_follow_link); |
diff --git a/fs/namespace.c b/fs/namespace.c index caa9187f67e5..2019899f2ab8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd) | |||
637 | if (current->uid != nd->dentry->d_inode->i_uid) | 637 | if (current->uid != nd->dentry->d_inode->i_uid) |
638 | return -EPERM; | 638 | return -EPERM; |
639 | } | 639 | } |
640 | if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) | 640 | if (vfs_permission(nd, MAY_WRITE)) |
641 | return -EPERM; | 641 | return -EPERM; |
642 | return 0; | 642 | return 0; |
643 | #endif | 643 | #endif |
@@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) | |||
240 | if (!S_ISREG(inode->i_mode)) | 240 | if (!S_ISREG(inode->i_mode)) |
241 | goto dput_and_out; | 241 | goto dput_and_out; |
242 | 242 | ||
243 | error = permission(inode,MAY_WRITE,&nd); | 243 | error = vfs_permission(&nd, MAY_WRITE); |
244 | if (error) | 244 | if (error) |
245 | goto dput_and_out; | 245 | goto dput_and_out; |
246 | 246 | ||
@@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) | |||
394 | goto dput_and_out; | 394 | goto dput_and_out; |
395 | 395 | ||
396 | if (current->fsuid != inode->i_uid && | 396 | if (current->fsuid != inode->i_uid && |
397 | (error = permission(inode,MAY_WRITE,&nd)) != 0) | 397 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) |
398 | goto dput_and_out; | 398 | goto dput_and_out; |
399 | } | 399 | } |
400 | down(&inode->i_sem); | 400 | down(&inode->i_sem); |
@@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times) | |||
447 | goto dput_and_out; | 447 | goto dput_and_out; |
448 | 448 | ||
449 | if (current->fsuid != inode->i_uid && | 449 | if (current->fsuid != inode->i_uid && |
450 | (error = permission(inode,MAY_WRITE,&nd)) != 0) | 450 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) |
451 | goto dput_and_out; | 451 | goto dput_and_out; |
452 | } | 452 | } |
453 | down(&inode->i_sem); | 453 | down(&inode->i_sem); |
@@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) | |||
506 | 506 | ||
507 | res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); | 507 | res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); |
508 | if (!res) { | 508 | if (!res) { |
509 | res = permission(nd.dentry->d_inode, mode, &nd); | 509 | res = vfs_permission(&nd, mode); |
510 | /* SuS v2 requires we report a read only fs too */ | 510 | /* SuS v2 requires we report a read only fs too */ |
511 | if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) | 511 | if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) |
512 | && !special_file(nd.dentry->d_inode->i_mode)) | 512 | && !special_file(nd.dentry->d_inode->i_mode)) |
@@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename) | |||
530 | if (error) | 530 | if (error) |
531 | goto out; | 531 | goto out; |
532 | 532 | ||
533 | error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); | 533 | error = vfs_permission(&nd, MAY_EXEC); |
534 | if (error) | 534 | if (error) |
535 | goto dput_and_out; | 535 | goto dput_and_out; |
536 | 536 | ||
@@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename) | |||
581 | if (error) | 581 | if (error) |
582 | goto out; | 582 | goto out; |
583 | 583 | ||
584 | error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); | 584 | error = vfs_permission(&nd, MAY_EXEC); |
585 | if (error) | 585 | if (error) |
586 | goto dput_and_out; | 586 | goto dput_and_out; |
587 | 587 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 1b5f502a4b8f..c3b8c1dc7cdf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb) | |||
874 | /* | 874 | /* |
875 | * VFS helper functions.. | 875 | * VFS helper functions.. |
876 | */ | 876 | */ |
877 | extern int vfs_permission(struct nameidata *, int); | ||
877 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 878 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); |
878 | extern int vfs_mkdir(struct inode *, struct dentry *, int); | 879 | extern int vfs_mkdir(struct inode *, struct dentry *, int); |
879 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); | 880 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 41feca3bef86..acc73ba8bade 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, | |||
676 | err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); | 676 | err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); |
677 | if (err) | 677 | if (err) |
678 | goto fail; | 678 | goto fail; |
679 | err = permission(nd.dentry->d_inode,MAY_WRITE, &nd); | 679 | err = vfs_permission(&nd, MAY_WRITE); |
680 | if (err) | 680 | if (err) |
681 | goto put_fail; | 681 | goto put_fail; |
682 | 682 | ||