diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 115 |
1 files changed, 75 insertions, 40 deletions
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..dd5c9f0bf829 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -226,6 +226,16 @@ int generic_permission(struct inode *inode, int mask, | |||
226 | return -EACCES; | 226 | return -EACCES; |
227 | } | 227 | } |
228 | 228 | ||
229 | /** | ||
230 | * inode_permission - check for access rights to a given inode | ||
231 | * @inode: inode to check permission on | ||
232 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
233 | * | ||
234 | * Used to check for read/write/execute permissions on an inode. | ||
235 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
236 | * for filesystem access without changing the "normal" uids which | ||
237 | * are used for other things. | ||
238 | */ | ||
229 | int inode_permission(struct inode *inode, int mask) | 239 | int inode_permission(struct inode *inode, int mask) |
230 | { | 240 | { |
231 | int retval; | 241 | int retval; |
@@ -247,7 +257,6 @@ int inode_permission(struct inode *inode, int mask) | |||
247 | return -EACCES; | 257 | return -EACCES; |
248 | } | 258 | } |
249 | 259 | ||
250 | /* Ordinary permission routines do not understand MAY_APPEND. */ | ||
251 | if (inode->i_op && inode->i_op->permission) | 260 | if (inode->i_op && inode->i_op->permission) |
252 | retval = inode->i_op->permission(inode, mask); | 261 | retval = inode->i_op->permission(inode, mask); |
253 | else | 262 | else |
@@ -265,21 +274,6 @@ int inode_permission(struct inode *inode, int mask) | |||
265 | } | 274 | } |
266 | 275 | ||
267 | /** | 276 | /** |
268 | * vfs_permission - check for access rights to a given path | ||
269 | * @nd: lookup result that describes the path | ||
270 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
271 | * | ||
272 | * Used to check for read/write/execute permissions on a path. | ||
273 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
274 | * for filesystem access without changing the "normal" uids which | ||
275 | * are used for other things. | ||
276 | */ | ||
277 | int vfs_permission(struct nameidata *nd, int mask) | ||
278 | { | ||
279 | return inode_permission(nd->path.dentry->d_inode, mask); | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * file_permission - check for additional access rights to a given file | 277 | * file_permission - check for additional access rights to a given file |
284 | * @file: file to check access rights for | 278 | * @file: file to check access rights for |
285 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 279 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
@@ -289,7 +283,7 @@ int vfs_permission(struct nameidata *nd, int mask) | |||
289 | * | 283 | * |
290 | * Note: | 284 | * Note: |
291 | * Do not use this function in new code. All access checks should | 285 | * Do not use this function in new code. All access checks should |
292 | * be done using vfs_permission(). | 286 | * be done using inode_permission(). |
293 | */ | 287 | */ |
294 | int file_permission(struct file *file, int mask) | 288 | int file_permission(struct file *file, int mask) |
295 | { | 289 | { |
@@ -527,18 +521,6 @@ out_unlock: | |||
527 | return result; | 521 | return result; |
528 | } | 522 | } |
529 | 523 | ||
530 | /* SMP-safe */ | ||
531 | static __always_inline void | ||
532 | walk_init_root(const char *name, struct nameidata *nd) | ||
533 | { | ||
534 | struct fs_struct *fs = current->fs; | ||
535 | |||
536 | read_lock(&fs->lock); | ||
537 | nd->path = fs->root; | ||
538 | path_get(&fs->root); | ||
539 | read_unlock(&fs->lock); | ||
540 | } | ||
541 | |||
542 | /* | 524 | /* |
543 | * Wrapper to retry pathname resolution whenever the underlying | 525 | * Wrapper to retry pathname resolution whenever the underlying |
544 | * file system returns an ESTALE. | 526 | * file system returns an ESTALE. |
@@ -576,9 +558,16 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
576 | goto fail; | 558 | goto fail; |
577 | 559 | ||
578 | if (*link == '/') { | 560 | if (*link == '/') { |
561 | struct fs_struct *fs = current->fs; | ||
562 | |||
579 | path_put(&nd->path); | 563 | path_put(&nd->path); |
580 | walk_init_root(link, nd); | 564 | |
565 | read_lock(&fs->lock); | ||
566 | nd->path = fs->root; | ||
567 | path_get(&fs->root); | ||
568 | read_unlock(&fs->lock); | ||
581 | } | 569 | } |
570 | |||
582 | res = link_path_walk(link, nd); | 571 | res = link_path_walk(link, nd); |
583 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 572 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
584 | return res; | 573 | return res; |
@@ -859,7 +848,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
859 | nd->flags |= LOOKUP_CONTINUE; | 848 | nd->flags |= LOOKUP_CONTINUE; |
860 | err = exec_permission_lite(inode); | 849 | err = exec_permission_lite(inode); |
861 | if (err == -EAGAIN) | 850 | if (err == -EAGAIN) |
862 | err = vfs_permission(nd, MAY_EXEC); | 851 | err = inode_permission(nd->path.dentry->d_inode, |
852 | MAY_EXEC); | ||
863 | if (err) | 853 | if (err) |
864 | break; | 854 | break; |
865 | 855 | ||
@@ -1493,9 +1483,9 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1493 | return error; | 1483 | return error; |
1494 | } | 1484 | } |
1495 | 1485 | ||
1496 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1486 | int may_open(struct path *path, int acc_mode, int flag) |
1497 | { | 1487 | { |
1498 | struct dentry *dentry = nd->path.dentry; | 1488 | struct dentry *dentry = path->dentry; |
1499 | struct inode *inode = dentry->d_inode; | 1489 | struct inode *inode = dentry->d_inode; |
1500 | int error; | 1490 | int error; |
1501 | 1491 | ||
@@ -1516,13 +1506,13 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1516 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1506 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
1517 | flag &= ~O_TRUNC; | 1507 | flag &= ~O_TRUNC; |
1518 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1508 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
1519 | if (nd->path.mnt->mnt_flags & MNT_NODEV) | 1509 | if (path->mnt->mnt_flags & MNT_NODEV) |
1520 | return -EACCES; | 1510 | return -EACCES; |
1521 | 1511 | ||
1522 | flag &= ~O_TRUNC; | 1512 | flag &= ~O_TRUNC; |
1523 | } | 1513 | } |
1524 | 1514 | ||
1525 | error = vfs_permission(nd, acc_mode); | 1515 | error = inode_permission(inode, acc_mode); |
1526 | if (error) | 1516 | if (error) |
1527 | return error; | 1517 | return error; |
1528 | /* | 1518 | /* |
@@ -1556,6 +1546,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1556 | * Refuse to truncate files with mandatory locks held on them. | 1546 | * Refuse to truncate files with mandatory locks held on them. |
1557 | */ | 1547 | */ |
1558 | error = locks_verify_locked(inode); | 1548 | error = locks_verify_locked(inode); |
1549 | if (!error) | ||
1550 | error = security_path_truncate(path, 0, | ||
1551 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
1559 | if (!error) { | 1552 | if (!error) { |
1560 | DQUOT_INIT(inode); | 1553 | DQUOT_INIT(inode); |
1561 | 1554 | ||
@@ -1586,14 +1579,18 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
1586 | 1579 | ||
1587 | if (!IS_POSIXACL(dir->d_inode)) | 1580 | if (!IS_POSIXACL(dir->d_inode)) |
1588 | mode &= ~current->fs->umask; | 1581 | mode &= ~current->fs->umask; |
1582 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
1583 | if (error) | ||
1584 | goto out_unlock; | ||
1589 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1585 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
1586 | out_unlock: | ||
1590 | mutex_unlock(&dir->d_inode->i_mutex); | 1587 | mutex_unlock(&dir->d_inode->i_mutex); |
1591 | dput(nd->path.dentry); | 1588 | dput(nd->path.dentry); |
1592 | nd->path.dentry = path->dentry; | 1589 | nd->path.dentry = path->dentry; |
1593 | if (error) | 1590 | if (error) |
1594 | return error; | 1591 | return error; |
1595 | /* Don't check for write permission, don't truncate */ | 1592 | /* Don't check for write permission, don't truncate */ |
1596 | return may_open(nd, 0, flag & ~O_TRUNC); | 1593 | return may_open(&nd->path, 0, flag & ~O_TRUNC); |
1597 | } | 1594 | } |
1598 | 1595 | ||
1599 | /* | 1596 | /* |
@@ -1779,7 +1776,7 @@ ok: | |||
1779 | if (error) | 1776 | if (error) |
1780 | goto exit; | 1777 | goto exit; |
1781 | } | 1778 | } |
1782 | error = may_open(&nd, acc_mode, flag); | 1779 | error = may_open(&nd.path, acc_mode, flag); |
1783 | if (error) { | 1780 | if (error) { |
1784 | if (will_write) | 1781 | if (will_write) |
1785 | mnt_drop_write(nd.path.mnt); | 1782 | mnt_drop_write(nd.path.mnt); |
@@ -1999,6 +1996,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1999 | error = mnt_want_write(nd.path.mnt); | 1996 | error = mnt_want_write(nd.path.mnt); |
2000 | if (error) | 1997 | if (error) |
2001 | goto out_dput; | 1998 | goto out_dput; |
1999 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
2000 | if (error) | ||
2001 | goto out_drop_write; | ||
2002 | switch (mode & S_IFMT) { | 2002 | switch (mode & S_IFMT) { |
2003 | case 0: case S_IFREG: | 2003 | case 0: case S_IFREG: |
2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
@@ -2011,6 +2011,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
2012 | break; | 2012 | break; |
2013 | } | 2013 | } |
2014 | out_drop_write: | ||
2014 | mnt_drop_write(nd.path.mnt); | 2015 | mnt_drop_write(nd.path.mnt); |
2015 | out_dput: | 2016 | out_dput: |
2016 | dput(dentry); | 2017 | dput(dentry); |
@@ -2070,7 +2071,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2070 | error = mnt_want_write(nd.path.mnt); | 2071 | error = mnt_want_write(nd.path.mnt); |
2071 | if (error) | 2072 | if (error) |
2072 | goto out_dput; | 2073 | goto out_dput; |
2074 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
2075 | if (error) | ||
2076 | goto out_drop_write; | ||
2073 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2077 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2078 | out_drop_write: | ||
2074 | mnt_drop_write(nd.path.mnt); | 2079 | mnt_drop_write(nd.path.mnt); |
2075 | out_dput: | 2080 | out_dput: |
2076 | dput(dentry); | 2081 | dput(dentry); |
@@ -2180,7 +2185,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2180 | error = mnt_want_write(nd.path.mnt); | 2185 | error = mnt_want_write(nd.path.mnt); |
2181 | if (error) | 2186 | if (error) |
2182 | goto exit3; | 2187 | goto exit3; |
2188 | error = security_path_rmdir(&nd.path, dentry); | ||
2189 | if (error) | ||
2190 | goto exit4; | ||
2183 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2191 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2192 | exit4: | ||
2184 | mnt_drop_write(nd.path.mnt); | 2193 | mnt_drop_write(nd.path.mnt); |
2185 | exit3: | 2194 | exit3: |
2186 | dput(dentry); | 2195 | dput(dentry); |
@@ -2265,7 +2274,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2265 | error = mnt_want_write(nd.path.mnt); | 2274 | error = mnt_want_write(nd.path.mnt); |
2266 | if (error) | 2275 | if (error) |
2267 | goto exit2; | 2276 | goto exit2; |
2277 | error = security_path_unlink(&nd.path, dentry); | ||
2278 | if (error) | ||
2279 | goto exit3; | ||
2268 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2280 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2281 | exit3: | ||
2269 | mnt_drop_write(nd.path.mnt); | 2282 | mnt_drop_write(nd.path.mnt); |
2270 | exit2: | 2283 | exit2: |
2271 | dput(dentry); | 2284 | dput(dentry); |
@@ -2346,7 +2359,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2346 | error = mnt_want_write(nd.path.mnt); | 2359 | error = mnt_want_write(nd.path.mnt); |
2347 | if (error) | 2360 | if (error) |
2348 | goto out_dput; | 2361 | goto out_dput; |
2362 | error = security_path_symlink(&nd.path, dentry, from); | ||
2363 | if (error) | ||
2364 | goto out_drop_write; | ||
2349 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2365 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
2366 | out_drop_write: | ||
2350 | mnt_drop_write(nd.path.mnt); | 2367 | mnt_drop_write(nd.path.mnt); |
2351 | out_dput: | 2368 | out_dput: |
2352 | dput(dentry); | 2369 | dput(dentry); |
@@ -2443,7 +2460,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2443 | error = mnt_want_write(nd.path.mnt); | 2460 | error = mnt_want_write(nd.path.mnt); |
2444 | if (error) | 2461 | if (error) |
2445 | goto out_dput; | 2462 | goto out_dput; |
2463 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
2464 | if (error) | ||
2465 | goto out_drop_write; | ||
2446 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2466 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
2467 | out_drop_write: | ||
2447 | mnt_drop_write(nd.path.mnt); | 2468 | mnt_drop_write(nd.path.mnt); |
2448 | out_dput: | 2469 | out_dput: |
2449 | dput(new_dentry); | 2470 | dput(new_dentry); |
@@ -2679,8 +2700,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
2679 | error = mnt_want_write(oldnd.path.mnt); | 2700 | error = mnt_want_write(oldnd.path.mnt); |
2680 | if (error) | 2701 | if (error) |
2681 | goto exit5; | 2702 | goto exit5; |
2703 | error = security_path_rename(&oldnd.path, old_dentry, | ||
2704 | &newnd.path, new_dentry); | ||
2705 | if (error) | ||
2706 | goto exit6; | ||
2682 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2707 | error = vfs_rename(old_dir->d_inode, old_dentry, |
2683 | new_dir->d_inode, new_dentry); | 2708 | new_dir->d_inode, new_dentry); |
2709 | exit6: | ||
2684 | mnt_drop_write(oldnd.path.mnt); | 2710 | mnt_drop_write(oldnd.path.mnt); |
2685 | exit5: | 2711 | exit5: |
2686 | dput(new_dentry); | 2712 | dput(new_dentry); |
@@ -2750,13 +2776,16 @@ int vfs_follow_link(struct nameidata *nd, const char *link) | |||
2750 | /* get the link contents into pagecache */ | 2776 | /* get the link contents into pagecache */ |
2751 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 2777 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
2752 | { | 2778 | { |
2753 | struct page * page; | 2779 | char *kaddr; |
2780 | struct page *page; | ||
2754 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2781 | struct address_space *mapping = dentry->d_inode->i_mapping; |
2755 | page = read_mapping_page(mapping, 0, NULL); | 2782 | page = read_mapping_page(mapping, 0, NULL); |
2756 | if (IS_ERR(page)) | 2783 | if (IS_ERR(page)) |
2757 | return (char*)page; | 2784 | return (char*)page; |
2758 | *ppage = page; | 2785 | *ppage = page; |
2759 | return kmap(page); | 2786 | kaddr = kmap(page); |
2787 | nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); | ||
2788 | return kaddr; | ||
2760 | } | 2789 | } |
2761 | 2790 | ||
2762 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2791 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
@@ -2849,7 +2878,6 @@ EXPORT_SYMBOL(path_lookup); | |||
2849 | EXPORT_SYMBOL(kern_path); | 2878 | EXPORT_SYMBOL(kern_path); |
2850 | EXPORT_SYMBOL(vfs_path_lookup); | 2879 | EXPORT_SYMBOL(vfs_path_lookup); |
2851 | EXPORT_SYMBOL(inode_permission); | 2880 | EXPORT_SYMBOL(inode_permission); |
2852 | EXPORT_SYMBOL(vfs_permission); | ||
2853 | EXPORT_SYMBOL(file_permission); | 2881 | EXPORT_SYMBOL(file_permission); |
2854 | EXPORT_SYMBOL(unlock_rename); | 2882 | EXPORT_SYMBOL(unlock_rename); |
2855 | EXPORT_SYMBOL(vfs_create); | 2883 | EXPORT_SYMBOL(vfs_create); |
@@ -2865,3 +2893,10 @@ EXPORT_SYMBOL(vfs_symlink); | |||
2865 | EXPORT_SYMBOL(vfs_unlink); | 2893 | EXPORT_SYMBOL(vfs_unlink); |
2866 | EXPORT_SYMBOL(dentry_unhash); | 2894 | EXPORT_SYMBOL(dentry_unhash); |
2867 | EXPORT_SYMBOL(generic_readlink); | 2895 | EXPORT_SYMBOL(generic_readlink); |
2896 | |||
2897 | /* to be mentioned only in INIT_TASK */ | ||
2898 | struct fs_struct init_fs = { | ||
2899 | .count = ATOMIC_INIT(1), | ||
2900 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
2901 | .umask = 0022, | ||
2902 | }; | ||