diff options
Diffstat (limited to 'fs/namei.c')
| -rw-r--r-- | fs/namei.c | 160 |
1 files changed, 97 insertions, 63 deletions
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..f05bed242422 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,8 +257,7 @@ 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. */ | 260 | if (inode->i_op->permission) |
| 251 | 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 |
| 254 | retval = generic_permission(inode, mask, NULL); | 263 | retval = generic_permission(inode, mask, NULL); |
| @@ -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 | { |
| @@ -438,7 +432,7 @@ static int exec_permission_lite(struct inode *inode) | |||
| 438 | { | 432 | { |
| 439 | umode_t mode = inode->i_mode; | 433 | umode_t mode = inode->i_mode; |
| 440 | 434 | ||
| 441 | if (inode->i_op && inode->i_op->permission) | 435 | if (inode->i_op->permission) |
| 442 | return -EAGAIN; | 436 | return -EAGAIN; |
| 443 | 437 | ||
| 444 | if (current_fsuid() == inode->i_uid) | 438 | if (current_fsuid() == inode->i_uid) |
| @@ -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 | ||
| @@ -918,9 +908,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
| 918 | inode = next.dentry->d_inode; | 908 | inode = next.dentry->d_inode; |
| 919 | if (!inode) | 909 | if (!inode) |
| 920 | goto out_dput; | 910 | goto out_dput; |
| 921 | err = -ENOTDIR; | ||
| 922 | if (!inode->i_op) | ||
| 923 | goto out_dput; | ||
| 924 | 911 | ||
| 925 | if (inode->i_op->follow_link) { | 912 | if (inode->i_op->follow_link) { |
| 926 | err = do_follow_link(&next, nd); | 913 | err = do_follow_link(&next, nd); |
| @@ -930,9 +917,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
| 930 | inode = nd->path.dentry->d_inode; | 917 | inode = nd->path.dentry->d_inode; |
| 931 | if (!inode) | 918 | if (!inode) |
| 932 | break; | 919 | break; |
| 933 | err = -ENOTDIR; | ||
| 934 | if (!inode->i_op) | ||
| 935 | break; | ||
| 936 | } else | 920 | } else |
| 937 | path_to_nameidata(&next, nd); | 921 | path_to_nameidata(&next, nd); |
| 938 | err = -ENOTDIR; | 922 | err = -ENOTDIR; |
| @@ -971,7 +955,7 @@ last_component: | |||
| 971 | break; | 955 | break; |
| 972 | inode = next.dentry->d_inode; | 956 | inode = next.dentry->d_inode; |
| 973 | if ((lookup_flags & LOOKUP_FOLLOW) | 957 | if ((lookup_flags & LOOKUP_FOLLOW) |
| 974 | && inode && inode->i_op && inode->i_op->follow_link) { | 958 | && inode && inode->i_op->follow_link) { |
| 975 | err = do_follow_link(&next, nd); | 959 | err = do_follow_link(&next, nd); |
| 976 | if (err) | 960 | if (err) |
| 977 | goto return_err; | 961 | goto return_err; |
| @@ -983,7 +967,7 @@ last_component: | |||
| 983 | break; | 967 | break; |
| 984 | if (lookup_flags & LOOKUP_DIRECTORY) { | 968 | if (lookup_flags & LOOKUP_DIRECTORY) { |
| 985 | err = -ENOTDIR; | 969 | err = -ENOTDIR; |
| 986 | if (!inode->i_op || !inode->i_op->lookup) | 970 | if (!inode->i_op->lookup) |
| 987 | break; | 971 | break; |
| 988 | } | 972 | } |
| 989 | goto return_base; | 973 | goto return_base; |
| @@ -1479,7 +1463,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1479 | if (error) | 1463 | if (error) |
| 1480 | return error; | 1464 | return error; |
| 1481 | 1465 | ||
| 1482 | if (!dir->i_op || !dir->i_op->create) | 1466 | if (!dir->i_op->create) |
| 1483 | return -EACCES; /* shouldn't it be ENOSYS? */ | 1467 | return -EACCES; /* shouldn't it be ENOSYS? */ |
| 1484 | mode &= S_IALLUGO; | 1468 | mode &= S_IALLUGO; |
| 1485 | mode |= S_IFREG; | 1469 | mode |= S_IFREG; |
| @@ -1493,9 +1477,9 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1493 | return error; | 1477 | return error; |
| 1494 | } | 1478 | } |
| 1495 | 1479 | ||
| 1496 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1480 | int may_open(struct path *path, int acc_mode, int flag) |
| 1497 | { | 1481 | { |
| 1498 | struct dentry *dentry = nd->path.dentry; | 1482 | struct dentry *dentry = path->dentry; |
| 1499 | struct inode *inode = dentry->d_inode; | 1483 | struct inode *inode = dentry->d_inode; |
| 1500 | int error; | 1484 | int error; |
| 1501 | 1485 | ||
| @@ -1516,13 +1500,13 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
| 1516 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1500 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
| 1517 | flag &= ~O_TRUNC; | 1501 | flag &= ~O_TRUNC; |
| 1518 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1502 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
| 1519 | if (nd->path.mnt->mnt_flags & MNT_NODEV) | 1503 | if (path->mnt->mnt_flags & MNT_NODEV) |
| 1520 | return -EACCES; | 1504 | return -EACCES; |
| 1521 | 1505 | ||
| 1522 | flag &= ~O_TRUNC; | 1506 | flag &= ~O_TRUNC; |
| 1523 | } | 1507 | } |
| 1524 | 1508 | ||
| 1525 | error = vfs_permission(nd, acc_mode); | 1509 | error = inode_permission(inode, acc_mode); |
| 1526 | if (error) | 1510 | if (error) |
| 1527 | return error; | 1511 | return error; |
| 1528 | /* | 1512 | /* |
| @@ -1556,6 +1540,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
| 1556 | * Refuse to truncate files with mandatory locks held on them. | 1540 | * Refuse to truncate files with mandatory locks held on them. |
| 1557 | */ | 1541 | */ |
| 1558 | error = locks_verify_locked(inode); | 1542 | error = locks_verify_locked(inode); |
| 1543 | if (!error) | ||
| 1544 | error = security_path_truncate(path, 0, | ||
| 1545 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
| 1559 | if (!error) { | 1546 | if (!error) { |
| 1560 | DQUOT_INIT(inode); | 1547 | DQUOT_INIT(inode); |
| 1561 | 1548 | ||
| @@ -1586,14 +1573,18 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
| 1586 | 1573 | ||
| 1587 | if (!IS_POSIXACL(dir->d_inode)) | 1574 | if (!IS_POSIXACL(dir->d_inode)) |
| 1588 | mode &= ~current->fs->umask; | 1575 | mode &= ~current->fs->umask; |
| 1576 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
| 1577 | if (error) | ||
| 1578 | goto out_unlock; | ||
| 1589 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1579 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
| 1580 | out_unlock: | ||
| 1590 | mutex_unlock(&dir->d_inode->i_mutex); | 1581 | mutex_unlock(&dir->d_inode->i_mutex); |
| 1591 | dput(nd->path.dentry); | 1582 | dput(nd->path.dentry); |
| 1592 | nd->path.dentry = path->dentry; | 1583 | nd->path.dentry = path->dentry; |
| 1593 | if (error) | 1584 | if (error) |
| 1594 | return error; | 1585 | return error; |
| 1595 | /* Don't check for write permission, don't truncate */ | 1586 | /* Don't check for write permission, don't truncate */ |
| 1596 | return may_open(nd, 0, flag & ~O_TRUNC); | 1587 | return may_open(&nd->path, 0, flag & ~O_TRUNC); |
| 1597 | } | 1588 | } |
| 1598 | 1589 | ||
| 1599 | /* | 1590 | /* |
| @@ -1755,7 +1746,7 @@ do_last: | |||
| 1755 | error = -ENOENT; | 1746 | error = -ENOENT; |
| 1756 | if (!path.dentry->d_inode) | 1747 | if (!path.dentry->d_inode) |
| 1757 | goto exit_dput; | 1748 | goto exit_dput; |
| 1758 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) | 1749 | if (path.dentry->d_inode->i_op->follow_link) |
| 1759 | goto do_link; | 1750 | goto do_link; |
| 1760 | 1751 | ||
| 1761 | path_to_nameidata(&path, &nd); | 1752 | path_to_nameidata(&path, &nd); |
| @@ -1779,7 +1770,7 @@ ok: | |||
| 1779 | if (error) | 1770 | if (error) |
| 1780 | goto exit; | 1771 | goto exit; |
| 1781 | } | 1772 | } |
| 1782 | error = may_open(&nd, acc_mode, flag); | 1773 | error = may_open(&nd.path, acc_mode, flag); |
| 1783 | if (error) { | 1774 | if (error) { |
| 1784 | if (will_write) | 1775 | if (will_write) |
| 1785 | mnt_drop_write(nd.path.mnt); | 1776 | mnt_drop_write(nd.path.mnt); |
| @@ -1936,7 +1927,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
| 1936 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) | 1927 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) |
| 1937 | return -EPERM; | 1928 | return -EPERM; |
| 1938 | 1929 | ||
| 1939 | if (!dir->i_op || !dir->i_op->mknod) | 1930 | if (!dir->i_op->mknod) |
| 1940 | return -EPERM; | 1931 | return -EPERM; |
| 1941 | 1932 | ||
| 1942 | error = devcgroup_inode_mknod(mode, dev); | 1933 | error = devcgroup_inode_mknod(mode, dev); |
| @@ -1999,6 +1990,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
| 1999 | error = mnt_want_write(nd.path.mnt); | 1990 | error = mnt_want_write(nd.path.mnt); |
| 2000 | if (error) | 1991 | if (error) |
| 2001 | goto out_dput; | 1992 | goto out_dput; |
| 1993 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
| 1994 | if (error) | ||
| 1995 | goto out_drop_write; | ||
| 2002 | switch (mode & S_IFMT) { | 1996 | switch (mode & S_IFMT) { |
| 2003 | case 0: case S_IFREG: | 1997 | case 0: case S_IFREG: |
| 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 1998 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
| @@ -2011,6 +2005,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); | 2005 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
| 2012 | break; | 2006 | break; |
| 2013 | } | 2007 | } |
| 2008 | out_drop_write: | ||
| 2014 | mnt_drop_write(nd.path.mnt); | 2009 | mnt_drop_write(nd.path.mnt); |
| 2015 | out_dput: | 2010 | out_dput: |
| 2016 | dput(dentry); | 2011 | dput(dentry); |
| @@ -2034,7 +2029,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 2034 | if (error) | 2029 | if (error) |
| 2035 | return error; | 2030 | return error; |
| 2036 | 2031 | ||
| 2037 | if (!dir->i_op || !dir->i_op->mkdir) | 2032 | if (!dir->i_op->mkdir) |
| 2038 | return -EPERM; | 2033 | return -EPERM; |
| 2039 | 2034 | ||
| 2040 | mode &= (S_IRWXUGO|S_ISVTX); | 2035 | mode &= (S_IRWXUGO|S_ISVTX); |
| @@ -2070,7 +2065,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
| 2070 | error = mnt_want_write(nd.path.mnt); | 2065 | error = mnt_want_write(nd.path.mnt); |
| 2071 | if (error) | 2066 | if (error) |
| 2072 | goto out_dput; | 2067 | goto out_dput; |
| 2068 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
| 2069 | if (error) | ||
| 2070 | goto out_drop_write; | ||
| 2073 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2071 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
| 2072 | out_drop_write: | ||
| 2074 | mnt_drop_write(nd.path.mnt); | 2073 | mnt_drop_write(nd.path.mnt); |
| 2075 | out_dput: | 2074 | out_dput: |
| 2076 | dput(dentry); | 2075 | dput(dentry); |
| @@ -2121,7 +2120,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 2121 | if (error) | 2120 | if (error) |
| 2122 | return error; | 2121 | return error; |
| 2123 | 2122 | ||
| 2124 | if (!dir->i_op || !dir->i_op->rmdir) | 2123 | if (!dir->i_op->rmdir) |
| 2125 | return -EPERM; | 2124 | return -EPERM; |
| 2126 | 2125 | ||
| 2127 | DQUOT_INIT(dir); | 2126 | DQUOT_INIT(dir); |
| @@ -2180,7 +2179,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
| 2180 | error = mnt_want_write(nd.path.mnt); | 2179 | error = mnt_want_write(nd.path.mnt); |
| 2181 | if (error) | 2180 | if (error) |
| 2182 | goto exit3; | 2181 | goto exit3; |
| 2182 | error = security_path_rmdir(&nd.path, dentry); | ||
| 2183 | if (error) | ||
| 2184 | goto exit4; | ||
| 2183 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2185 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
| 2186 | exit4: | ||
| 2184 | mnt_drop_write(nd.path.mnt); | 2187 | mnt_drop_write(nd.path.mnt); |
| 2185 | exit3: | 2188 | exit3: |
| 2186 | dput(dentry); | 2189 | dput(dentry); |
| @@ -2204,7 +2207,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 2204 | if (error) | 2207 | if (error) |
| 2205 | return error; | 2208 | return error; |
| 2206 | 2209 | ||
| 2207 | if (!dir->i_op || !dir->i_op->unlink) | 2210 | if (!dir->i_op->unlink) |
| 2208 | return -EPERM; | 2211 | return -EPERM; |
| 2209 | 2212 | ||
| 2210 | DQUOT_INIT(dir); | 2213 | DQUOT_INIT(dir); |
| @@ -2265,7 +2268,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 2265 | error = mnt_want_write(nd.path.mnt); | 2268 | error = mnt_want_write(nd.path.mnt); |
| 2266 | if (error) | 2269 | if (error) |
| 2267 | goto exit2; | 2270 | goto exit2; |
| 2271 | error = security_path_unlink(&nd.path, dentry); | ||
| 2272 | if (error) | ||
| 2273 | goto exit3; | ||
| 2268 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2274 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
| 2275 | exit3: | ||
| 2269 | mnt_drop_write(nd.path.mnt); | 2276 | mnt_drop_write(nd.path.mnt); |
| 2270 | exit2: | 2277 | exit2: |
| 2271 | dput(dentry); | 2278 | dput(dentry); |
| @@ -2307,7 +2314,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | |||
| 2307 | if (error) | 2314 | if (error) |
| 2308 | return error; | 2315 | return error; |
| 2309 | 2316 | ||
| 2310 | if (!dir->i_op || !dir->i_op->symlink) | 2317 | if (!dir->i_op->symlink) |
| 2311 | return -EPERM; | 2318 | return -EPERM; |
| 2312 | 2319 | ||
| 2313 | error = security_inode_symlink(dir, dentry, oldname); | 2320 | error = security_inode_symlink(dir, dentry, oldname); |
| @@ -2346,7 +2353,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
| 2346 | error = mnt_want_write(nd.path.mnt); | 2353 | error = mnt_want_write(nd.path.mnt); |
| 2347 | if (error) | 2354 | if (error) |
| 2348 | goto out_dput; | 2355 | goto out_dput; |
| 2356 | error = security_path_symlink(&nd.path, dentry, from); | ||
| 2357 | if (error) | ||
| 2358 | goto out_drop_write; | ||
| 2349 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2359 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
| 2360 | out_drop_write: | ||
| 2350 | mnt_drop_write(nd.path.mnt); | 2361 | mnt_drop_write(nd.path.mnt); |
| 2351 | out_dput: | 2362 | out_dput: |
| 2352 | dput(dentry); | 2363 | dput(dentry); |
| @@ -2384,7 +2395,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
| 2384 | */ | 2395 | */ |
| 2385 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 2396 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
| 2386 | return -EPERM; | 2397 | return -EPERM; |
| 2387 | if (!dir->i_op || !dir->i_op->link) | 2398 | if (!dir->i_op->link) |
| 2388 | return -EPERM; | 2399 | return -EPERM; |
| 2389 | if (S_ISDIR(inode->i_mode)) | 2400 | if (S_ISDIR(inode->i_mode)) |
| 2390 | return -EPERM; | 2401 | return -EPERM; |
| @@ -2443,7 +2454,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
| 2443 | error = mnt_want_write(nd.path.mnt); | 2454 | error = mnt_want_write(nd.path.mnt); |
| 2444 | if (error) | 2455 | if (error) |
| 2445 | goto out_dput; | 2456 | goto out_dput; |
| 2457 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
| 2458 | if (error) | ||
| 2459 | goto out_drop_write; | ||
| 2446 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2460 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
| 2461 | out_drop_write: | ||
| 2447 | mnt_drop_write(nd.path.mnt); | 2462 | mnt_drop_write(nd.path.mnt); |
| 2448 | out_dput: | 2463 | out_dput: |
| 2449 | dput(new_dentry); | 2464 | dput(new_dentry); |
| @@ -2587,7 +2602,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 2587 | if (error) | 2602 | if (error) |
| 2588 | return error; | 2603 | return error; |
| 2589 | 2604 | ||
| 2590 | if (!old_dir->i_op || !old_dir->i_op->rename) | 2605 | if (!old_dir->i_op->rename) |
| 2591 | return -EPERM; | 2606 | return -EPERM; |
| 2592 | 2607 | ||
| 2593 | DQUOT_INIT(old_dir); | 2608 | DQUOT_INIT(old_dir); |
| @@ -2679,8 +2694,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
| 2679 | error = mnt_want_write(oldnd.path.mnt); | 2694 | error = mnt_want_write(oldnd.path.mnt); |
| 2680 | if (error) | 2695 | if (error) |
| 2681 | goto exit5; | 2696 | goto exit5; |
| 2697 | error = security_path_rename(&oldnd.path, old_dentry, | ||
| 2698 | &newnd.path, new_dentry); | ||
| 2699 | if (error) | ||
| 2700 | goto exit6; | ||
| 2682 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2701 | error = vfs_rename(old_dir->d_inode, old_dentry, |
| 2683 | new_dir->d_inode, new_dentry); | 2702 | new_dir->d_inode, new_dentry); |
| 2703 | exit6: | ||
| 2684 | mnt_drop_write(oldnd.path.mnt); | 2704 | mnt_drop_write(oldnd.path.mnt); |
| 2685 | exit5: | 2705 | exit5: |
| 2686 | dput(new_dentry); | 2706 | dput(new_dentry); |
| @@ -2750,13 +2770,16 @@ int vfs_follow_link(struct nameidata *nd, const char *link) | |||
| 2750 | /* get the link contents into pagecache */ | 2770 | /* get the link contents into pagecache */ |
| 2751 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 2771 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
| 2752 | { | 2772 | { |
| 2753 | struct page * page; | 2773 | char *kaddr; |
| 2774 | struct page *page; | ||
| 2754 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2775 | struct address_space *mapping = dentry->d_inode->i_mapping; |
| 2755 | page = read_mapping_page(mapping, 0, NULL); | 2776 | page = read_mapping_page(mapping, 0, NULL); |
| 2756 | if (IS_ERR(page)) | 2777 | if (IS_ERR(page)) |
| 2757 | return (char*)page; | 2778 | return (char*)page; |
| 2758 | *ppage = page; | 2779 | *ppage = page; |
| 2759 | return kmap(page); | 2780 | kaddr = kmap(page); |
| 2781 | nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); | ||
| 2782 | return kaddr; | ||
| 2760 | } | 2783 | } |
| 2761 | 2784 | ||
| 2762 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2785 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
| @@ -2788,18 +2811,23 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | |||
| 2788 | } | 2811 | } |
| 2789 | } | 2812 | } |
| 2790 | 2813 | ||
| 2791 | int __page_symlink(struct inode *inode, const char *symname, int len, | 2814 | /* |
| 2792 | gfp_t gfp_mask) | 2815 | * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS |
| 2816 | */ | ||
| 2817 | int __page_symlink(struct inode *inode, const char *symname, int len, int nofs) | ||
| 2793 | { | 2818 | { |
| 2794 | struct address_space *mapping = inode->i_mapping; | 2819 | struct address_space *mapping = inode->i_mapping; |
| 2795 | struct page *page; | 2820 | struct page *page; |
| 2796 | void *fsdata; | 2821 | void *fsdata; |
| 2797 | int err; | 2822 | int err; |
| 2798 | char *kaddr; | 2823 | char *kaddr; |
| 2824 | unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE; | ||
| 2825 | if (nofs) | ||
| 2826 | flags |= AOP_FLAG_NOFS; | ||
| 2799 | 2827 | ||
| 2800 | retry: | 2828 | retry: |
| 2801 | err = pagecache_write_begin(NULL, mapping, 0, len-1, | 2829 | err = pagecache_write_begin(NULL, mapping, 0, len-1, |
| 2802 | AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata); | 2830 | flags, &page, &fsdata); |
| 2803 | if (err) | 2831 | if (err) |
| 2804 | goto fail; | 2832 | goto fail; |
| 2805 | 2833 | ||
| @@ -2823,7 +2851,7 @@ fail: | |||
| 2823 | int page_symlink(struct inode *inode, const char *symname, int len) | 2851 | int page_symlink(struct inode *inode, const char *symname, int len) |
| 2824 | { | 2852 | { |
| 2825 | return __page_symlink(inode, symname, len, | 2853 | return __page_symlink(inode, symname, len, |
| 2826 | mapping_gfp_mask(inode->i_mapping)); | 2854 | !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS)); |
| 2827 | } | 2855 | } |
| 2828 | 2856 | ||
| 2829 | const struct inode_operations page_symlink_inode_operations = { | 2857 | const struct inode_operations page_symlink_inode_operations = { |
| @@ -2849,7 +2877,6 @@ EXPORT_SYMBOL(path_lookup); | |||
| 2849 | EXPORT_SYMBOL(kern_path); | 2877 | EXPORT_SYMBOL(kern_path); |
| 2850 | EXPORT_SYMBOL(vfs_path_lookup); | 2878 | EXPORT_SYMBOL(vfs_path_lookup); |
| 2851 | EXPORT_SYMBOL(inode_permission); | 2879 | EXPORT_SYMBOL(inode_permission); |
| 2852 | EXPORT_SYMBOL(vfs_permission); | ||
| 2853 | EXPORT_SYMBOL(file_permission); | 2880 | EXPORT_SYMBOL(file_permission); |
| 2854 | EXPORT_SYMBOL(unlock_rename); | 2881 | EXPORT_SYMBOL(unlock_rename); |
| 2855 | EXPORT_SYMBOL(vfs_create); | 2882 | EXPORT_SYMBOL(vfs_create); |
| @@ -2865,3 +2892,10 @@ EXPORT_SYMBOL(vfs_symlink); | |||
| 2865 | EXPORT_SYMBOL(vfs_unlink); | 2892 | EXPORT_SYMBOL(vfs_unlink); |
| 2866 | EXPORT_SYMBOL(dentry_unhash); | 2893 | EXPORT_SYMBOL(dentry_unhash); |
| 2867 | EXPORT_SYMBOL(generic_readlink); | 2894 | EXPORT_SYMBOL(generic_readlink); |
| 2895 | |||
| 2896 | /* to be mentioned only in INIT_TASK */ | ||
| 2897 | struct fs_struct init_fs = { | ||
| 2898 | .count = ATOMIC_INIT(1), | ||
| 2899 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
| 2900 | .umask = 0022, | ||
| 2901 | }; | ||
