diff options
author | James Morris <jmorris@namei.org> | 2009-02-05 19:01:45 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-02-05 19:01:45 -0500 |
commit | cb5629b10d64a8006622ce3a52bc887d91057d69 (patch) | |
tree | 7c06d8f30783115e3384721046258ce615b129c5 /fs/namei.c | |
parent | 8920d5ad6ba74ae8ab020e90cc4d976980e68701 (diff) | |
parent | f01d1d546abb2f4028b5299092f529eefb01253a (diff) |
Merge branch 'master' into next
Conflicts:
fs/namei.c
Manually merged per:
diff --cc fs/namei.c
index 734f2b5,bbc15c2..0000000
--- a/fs/namei.c
+++ b/fs/namei.c
@@@ -860,9 -848,8 +849,10 @@@ static int __link_path_walk(const char
nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode);
if (err == -EAGAIN)
- err = vfs_permission(nd, MAY_EXEC);
+ err = inode_permission(nd->path.dentry->d_inode,
+ MAY_EXEC);
+ if (!err)
+ err = ima_path_check(&nd->path, MAY_EXEC);
if (err)
break;
@@@ -1525,14 -1506,9 +1509,14 @@@ int may_open(struct path *path, int acc
flag &= ~O_TRUNC;
}
- error = vfs_permission(nd, acc_mode);
+ error = inode_permission(inode, acc_mode);
if (error)
return error;
+
- error = ima_path_check(&nd->path,
++ error = ima_path_check(path,
+ acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+ if (error)
+ return error;
/*
* An append-only file must be opened in append mode for writing.
*/
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 197 |
1 files changed, 115 insertions, 82 deletions
diff --git a/fs/namei.c b/fs/namei.c index 734f2b5591bf..199317642ad6 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -227,6 +227,16 @@ int generic_permission(struct inode *inode, int mask, | |||
227 | return -EACCES; | 227 | return -EACCES; |
228 | } | 228 | } |
229 | 229 | ||
230 | /** | ||
231 | * inode_permission - check for access rights to a given inode | ||
232 | * @inode: inode to check permission on | ||
233 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
234 | * | ||
235 | * Used to check for read/write/execute permissions on an inode. | ||
236 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
237 | * for filesystem access without changing the "normal" uids which | ||
238 | * are used for other things. | ||
239 | */ | ||
230 | int inode_permission(struct inode *inode, int mask) | 240 | int inode_permission(struct inode *inode, int mask) |
231 | { | 241 | { |
232 | int retval; | 242 | int retval; |
@@ -248,8 +258,7 @@ int inode_permission(struct inode *inode, int mask) | |||
248 | return -EACCES; | 258 | return -EACCES; |
249 | } | 259 | } |
250 | 260 | ||
251 | /* Ordinary permission routines do not understand MAY_APPEND. */ | 261 | if (inode->i_op->permission) |
252 | if (inode->i_op && inode->i_op->permission) | ||
253 | retval = inode->i_op->permission(inode, mask); | 262 | retval = inode->i_op->permission(inode, mask); |
254 | else | 263 | else |
255 | retval = generic_permission(inode, mask, NULL); | 264 | retval = generic_permission(inode, mask, NULL); |
@@ -266,21 +275,6 @@ int inode_permission(struct inode *inode, int mask) | |||
266 | } | 275 | } |
267 | 276 | ||
268 | /** | 277 | /** |
269 | * vfs_permission - check for access rights to a given path | ||
270 | * @nd: lookup result that describes the path | ||
271 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
272 | * | ||
273 | * Used to check for read/write/execute permissions on a path. | ||
274 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
275 | * for filesystem access without changing the "normal" uids which | ||
276 | * are used for other things. | ||
277 | */ | ||
278 | int vfs_permission(struct nameidata *nd, int mask) | ||
279 | { | ||
280 | return inode_permission(nd->path.dentry->d_inode, mask); | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * file_permission - check for additional access rights to a given file | 278 | * file_permission - check for additional access rights to a given file |
285 | * @file: file to check access rights for | 279 | * @file: file to check access rights for |
286 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 280 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
@@ -290,7 +284,7 @@ int vfs_permission(struct nameidata *nd, int mask) | |||
290 | * | 284 | * |
291 | * Note: | 285 | * Note: |
292 | * Do not use this function in new code. All access checks should | 286 | * Do not use this function in new code. All access checks should |
293 | * be done using vfs_permission(). | 287 | * be done using inode_permission(). |
294 | */ | 288 | */ |
295 | int file_permission(struct file *file, int mask) | 289 | int file_permission(struct file *file, int mask) |
296 | { | 290 | { |
@@ -439,7 +433,7 @@ static int exec_permission_lite(struct inode *inode) | |||
439 | { | 433 | { |
440 | umode_t mode = inode->i_mode; | 434 | umode_t mode = inode->i_mode; |
441 | 435 | ||
442 | if (inode->i_op && inode->i_op->permission) | 436 | if (inode->i_op->permission) |
443 | return -EAGAIN; | 437 | return -EAGAIN; |
444 | 438 | ||
445 | if (current_fsuid() == inode->i_uid) | 439 | if (current_fsuid() == inode->i_uid) |
@@ -528,18 +522,6 @@ out_unlock: | |||
528 | return result; | 522 | return result; |
529 | } | 523 | } |
530 | 524 | ||
531 | /* SMP-safe */ | ||
532 | static __always_inline void | ||
533 | walk_init_root(const char *name, struct nameidata *nd) | ||
534 | { | ||
535 | struct fs_struct *fs = current->fs; | ||
536 | |||
537 | read_lock(&fs->lock); | ||
538 | nd->path = fs->root; | ||
539 | path_get(&fs->root); | ||
540 | read_unlock(&fs->lock); | ||
541 | } | ||
542 | |||
543 | /* | 525 | /* |
544 | * Wrapper to retry pathname resolution whenever the underlying | 526 | * Wrapper to retry pathname resolution whenever the underlying |
545 | * file system returns an ESTALE. | 527 | * file system returns an ESTALE. |
@@ -577,9 +559,16 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
577 | goto fail; | 559 | goto fail; |
578 | 560 | ||
579 | if (*link == '/') { | 561 | if (*link == '/') { |
562 | struct fs_struct *fs = current->fs; | ||
563 | |||
580 | path_put(&nd->path); | 564 | path_put(&nd->path); |
581 | walk_init_root(link, nd); | 565 | |
566 | read_lock(&fs->lock); | ||
567 | nd->path = fs->root; | ||
568 | path_get(&fs->root); | ||
569 | read_unlock(&fs->lock); | ||
582 | } | 570 | } |
571 | |||
583 | res = link_path_walk(link, nd); | 572 | res = link_path_walk(link, nd); |
584 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 573 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
585 | return res; | 574 | return res; |
@@ -860,7 +849,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
860 | nd->flags |= LOOKUP_CONTINUE; | 849 | nd->flags |= LOOKUP_CONTINUE; |
861 | err = exec_permission_lite(inode); | 850 | err = exec_permission_lite(inode); |
862 | if (err == -EAGAIN) | 851 | if (err == -EAGAIN) |
863 | err = vfs_permission(nd, MAY_EXEC); | 852 | err = inode_permission(nd->path.dentry->d_inode, |
853 | MAY_EXEC); | ||
864 | if (!err) | 854 | if (!err) |
865 | err = ima_path_check(&nd->path, MAY_EXEC); | 855 | err = ima_path_check(&nd->path, MAY_EXEC); |
866 | if (err) | 856 | if (err) |
@@ -921,9 +911,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
921 | inode = next.dentry->d_inode; | 911 | inode = next.dentry->d_inode; |
922 | if (!inode) | 912 | if (!inode) |
923 | goto out_dput; | 913 | goto out_dput; |
924 | err = -ENOTDIR; | ||
925 | if (!inode->i_op) | ||
926 | goto out_dput; | ||
927 | 914 | ||
928 | if (inode->i_op->follow_link) { | 915 | if (inode->i_op->follow_link) { |
929 | err = do_follow_link(&next, nd); | 916 | err = do_follow_link(&next, nd); |
@@ -933,9 +920,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
933 | inode = nd->path.dentry->d_inode; | 920 | inode = nd->path.dentry->d_inode; |
934 | if (!inode) | 921 | if (!inode) |
935 | break; | 922 | break; |
936 | err = -ENOTDIR; | ||
937 | if (!inode->i_op) | ||
938 | break; | ||
939 | } else | 923 | } else |
940 | path_to_nameidata(&next, nd); | 924 | path_to_nameidata(&next, nd); |
941 | err = -ENOTDIR; | 925 | err = -ENOTDIR; |
@@ -974,7 +958,7 @@ last_component: | |||
974 | break; | 958 | break; |
975 | inode = next.dentry->d_inode; | 959 | inode = next.dentry->d_inode; |
976 | if ((lookup_flags & LOOKUP_FOLLOW) | 960 | if ((lookup_flags & LOOKUP_FOLLOW) |
977 | && inode && inode->i_op && inode->i_op->follow_link) { | 961 | && inode && inode->i_op->follow_link) { |
978 | err = do_follow_link(&next, nd); | 962 | err = do_follow_link(&next, nd); |
979 | if (err) | 963 | if (err) |
980 | goto return_err; | 964 | goto return_err; |
@@ -986,7 +970,7 @@ last_component: | |||
986 | break; | 970 | break; |
987 | if (lookup_flags & LOOKUP_DIRECTORY) { | 971 | if (lookup_flags & LOOKUP_DIRECTORY) { |
988 | err = -ENOTDIR; | 972 | err = -ENOTDIR; |
989 | if (!inode->i_op || !inode->i_op->lookup) | 973 | if (!inode->i_op->lookup) |
990 | break; | 974 | break; |
991 | } | 975 | } |
992 | goto return_base; | 976 | goto return_base; |
@@ -1482,7 +1466,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1482 | if (error) | 1466 | if (error) |
1483 | return error; | 1467 | return error; |
1484 | 1468 | ||
1485 | if (!dir->i_op || !dir->i_op->create) | 1469 | if (!dir->i_op->create) |
1486 | return -EACCES; /* shouldn't it be ENOSYS? */ | 1470 | return -EACCES; /* shouldn't it be ENOSYS? */ |
1487 | mode &= S_IALLUGO; | 1471 | mode &= S_IALLUGO; |
1488 | mode |= S_IFREG; | 1472 | mode |= S_IFREG; |
@@ -1496,9 +1480,9 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1496 | return error; | 1480 | return error; |
1497 | } | 1481 | } |
1498 | 1482 | ||
1499 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1483 | int may_open(struct path *path, int acc_mode, int flag) |
1500 | { | 1484 | { |
1501 | struct dentry *dentry = nd->path.dentry; | 1485 | struct dentry *dentry = path->dentry; |
1502 | struct inode *inode = dentry->d_inode; | 1486 | struct inode *inode = dentry->d_inode; |
1503 | int error; | 1487 | int error; |
1504 | 1488 | ||
@@ -1519,17 +1503,17 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1519 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1503 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
1520 | flag &= ~O_TRUNC; | 1504 | flag &= ~O_TRUNC; |
1521 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1505 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
1522 | if (nd->path.mnt->mnt_flags & MNT_NODEV) | 1506 | if (path->mnt->mnt_flags & MNT_NODEV) |
1523 | return -EACCES; | 1507 | return -EACCES; |
1524 | 1508 | ||
1525 | flag &= ~O_TRUNC; | 1509 | flag &= ~O_TRUNC; |
1526 | } | 1510 | } |
1527 | 1511 | ||
1528 | error = vfs_permission(nd, acc_mode); | 1512 | error = inode_permission(inode, acc_mode); |
1529 | if (error) | 1513 | if (error) |
1530 | return error; | 1514 | return error; |
1531 | 1515 | ||
1532 | error = ima_path_check(&nd->path, | 1516 | error = ima_path_check(path, |
1533 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); | 1517 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); |
1534 | if (error) | 1518 | if (error) |
1535 | return error; | 1519 | return error; |
@@ -1564,6 +1548,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1564 | * Refuse to truncate files with mandatory locks held on them. | 1548 | * Refuse to truncate files with mandatory locks held on them. |
1565 | */ | 1549 | */ |
1566 | error = locks_verify_locked(inode); | 1550 | error = locks_verify_locked(inode); |
1551 | if (!error) | ||
1552 | error = security_path_truncate(path, 0, | ||
1553 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
1567 | if (!error) { | 1554 | if (!error) { |
1568 | DQUOT_INIT(inode); | 1555 | DQUOT_INIT(inode); |
1569 | 1556 | ||
@@ -1594,14 +1581,18 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
1594 | 1581 | ||
1595 | if (!IS_POSIXACL(dir->d_inode)) | 1582 | if (!IS_POSIXACL(dir->d_inode)) |
1596 | mode &= ~current->fs->umask; | 1583 | mode &= ~current->fs->umask; |
1584 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
1585 | if (error) | ||
1586 | goto out_unlock; | ||
1597 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1587 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
1588 | out_unlock: | ||
1598 | mutex_unlock(&dir->d_inode->i_mutex); | 1589 | mutex_unlock(&dir->d_inode->i_mutex); |
1599 | dput(nd->path.dentry); | 1590 | dput(nd->path.dentry); |
1600 | nd->path.dentry = path->dentry; | 1591 | nd->path.dentry = path->dentry; |
1601 | if (error) | 1592 | if (error) |
1602 | return error; | 1593 | return error; |
1603 | /* Don't check for write permission, don't truncate */ | 1594 | /* Don't check for write permission, don't truncate */ |
1604 | return may_open(nd, 0, flag & ~O_TRUNC); | 1595 | return may_open(&nd->path, 0, flag & ~O_TRUNC); |
1605 | } | 1596 | } |
1606 | 1597 | ||
1607 | /* | 1598 | /* |
@@ -1763,7 +1754,7 @@ do_last: | |||
1763 | error = -ENOENT; | 1754 | error = -ENOENT; |
1764 | if (!path.dentry->d_inode) | 1755 | if (!path.dentry->d_inode) |
1765 | goto exit_dput; | 1756 | goto exit_dput; |
1766 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) | 1757 | if (path.dentry->d_inode->i_op->follow_link) |
1767 | goto do_link; | 1758 | goto do_link; |
1768 | 1759 | ||
1769 | path_to_nameidata(&path, &nd); | 1760 | path_to_nameidata(&path, &nd); |
@@ -1787,7 +1778,7 @@ ok: | |||
1787 | if (error) | 1778 | if (error) |
1788 | goto exit; | 1779 | goto exit; |
1789 | } | 1780 | } |
1790 | error = may_open(&nd, acc_mode, flag); | 1781 | error = may_open(&nd.path, acc_mode, flag); |
1791 | if (error) { | 1782 | if (error) { |
1792 | if (will_write) | 1783 | if (will_write) |
1793 | mnt_drop_write(nd.path.mnt); | 1784 | mnt_drop_write(nd.path.mnt); |
@@ -1944,7 +1935,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1944 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) | 1935 | if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) |
1945 | return -EPERM; | 1936 | return -EPERM; |
1946 | 1937 | ||
1947 | if (!dir->i_op || !dir->i_op->mknod) | 1938 | if (!dir->i_op->mknod) |
1948 | return -EPERM; | 1939 | return -EPERM; |
1949 | 1940 | ||
1950 | error = devcgroup_inode_mknod(mode, dev); | 1941 | error = devcgroup_inode_mknod(mode, dev); |
@@ -1979,8 +1970,8 @@ static int may_mknod(mode_t mode) | |||
1979 | } | 1970 | } |
1980 | } | 1971 | } |
1981 | 1972 | ||
1982 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | 1973 | SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, |
1983 | unsigned dev) | 1974 | unsigned, dev) |
1984 | { | 1975 | { |
1985 | int error; | 1976 | int error; |
1986 | char *tmp; | 1977 | char *tmp; |
@@ -2007,6 +1998,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
2007 | error = mnt_want_write(nd.path.mnt); | 1998 | error = mnt_want_write(nd.path.mnt); |
2008 | if (error) | 1999 | if (error) |
2009 | goto out_dput; | 2000 | goto out_dput; |
2001 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
2002 | if (error) | ||
2003 | goto out_drop_write; | ||
2010 | switch (mode & S_IFMT) { | 2004 | switch (mode & S_IFMT) { |
2011 | case 0: case S_IFREG: | 2005 | case 0: case S_IFREG: |
2012 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2006 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
@@ -2019,6 +2013,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
2019 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2013 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
2020 | break; | 2014 | break; |
2021 | } | 2015 | } |
2016 | out_drop_write: | ||
2022 | mnt_drop_write(nd.path.mnt); | 2017 | mnt_drop_write(nd.path.mnt); |
2023 | out_dput: | 2018 | out_dput: |
2024 | dput(dentry); | 2019 | dput(dentry); |
@@ -2030,7 +2025,7 @@ out_unlock: | |||
2030 | return error; | 2025 | return error; |
2031 | } | 2026 | } |
2032 | 2027 | ||
2033 | asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev) | 2028 | SYSCALL_DEFINE3(mknod, const char __user *, filename, int, mode, unsigned, dev) |
2034 | { | 2029 | { |
2035 | return sys_mknodat(AT_FDCWD, filename, mode, dev); | 2030 | return sys_mknodat(AT_FDCWD, filename, mode, dev); |
2036 | } | 2031 | } |
@@ -2042,7 +2037,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
2042 | if (error) | 2037 | if (error) |
2043 | return error; | 2038 | return error; |
2044 | 2039 | ||
2045 | if (!dir->i_op || !dir->i_op->mkdir) | 2040 | if (!dir->i_op->mkdir) |
2046 | return -EPERM; | 2041 | return -EPERM; |
2047 | 2042 | ||
2048 | mode &= (S_IRWXUGO|S_ISVTX); | 2043 | mode &= (S_IRWXUGO|S_ISVTX); |
@@ -2057,7 +2052,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
2057 | return error; | 2052 | return error; |
2058 | } | 2053 | } |
2059 | 2054 | ||
2060 | asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | 2055 | SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) |
2061 | { | 2056 | { |
2062 | int error = 0; | 2057 | int error = 0; |
2063 | char * tmp; | 2058 | char * tmp; |
@@ -2078,7 +2073,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2078 | error = mnt_want_write(nd.path.mnt); | 2073 | error = mnt_want_write(nd.path.mnt); |
2079 | if (error) | 2074 | if (error) |
2080 | goto out_dput; | 2075 | goto out_dput; |
2076 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
2077 | if (error) | ||
2078 | goto out_drop_write; | ||
2081 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2079 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2080 | out_drop_write: | ||
2082 | mnt_drop_write(nd.path.mnt); | 2081 | mnt_drop_write(nd.path.mnt); |
2083 | out_dput: | 2082 | out_dput: |
2084 | dput(dentry); | 2083 | dput(dentry); |
@@ -2090,7 +2089,7 @@ out_err: | |||
2090 | return error; | 2089 | return error; |
2091 | } | 2090 | } |
2092 | 2091 | ||
2093 | asmlinkage long sys_mkdir(const char __user *pathname, int mode) | 2092 | SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode) |
2094 | { | 2093 | { |
2095 | return sys_mkdirat(AT_FDCWD, pathname, mode); | 2094 | return sys_mkdirat(AT_FDCWD, pathname, mode); |
2096 | } | 2095 | } |
@@ -2129,7 +2128,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2129 | if (error) | 2128 | if (error) |
2130 | return error; | 2129 | return error; |
2131 | 2130 | ||
2132 | if (!dir->i_op || !dir->i_op->rmdir) | 2131 | if (!dir->i_op->rmdir) |
2133 | return -EPERM; | 2132 | return -EPERM; |
2134 | 2133 | ||
2135 | DQUOT_INIT(dir); | 2134 | DQUOT_INIT(dir); |
@@ -2188,7 +2187,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2188 | error = mnt_want_write(nd.path.mnt); | 2187 | error = mnt_want_write(nd.path.mnt); |
2189 | if (error) | 2188 | if (error) |
2190 | goto exit3; | 2189 | goto exit3; |
2190 | error = security_path_rmdir(&nd.path, dentry); | ||
2191 | if (error) | ||
2192 | goto exit4; | ||
2191 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2193 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2194 | exit4: | ||
2192 | mnt_drop_write(nd.path.mnt); | 2195 | mnt_drop_write(nd.path.mnt); |
2193 | exit3: | 2196 | exit3: |
2194 | dput(dentry); | 2197 | dput(dentry); |
@@ -2200,7 +2203,7 @@ exit1: | |||
2200 | return error; | 2203 | return error; |
2201 | } | 2204 | } |
2202 | 2205 | ||
2203 | asmlinkage long sys_rmdir(const char __user *pathname) | 2206 | SYSCALL_DEFINE1(rmdir, const char __user *, pathname) |
2204 | { | 2207 | { |
2205 | return do_rmdir(AT_FDCWD, pathname); | 2208 | return do_rmdir(AT_FDCWD, pathname); |
2206 | } | 2209 | } |
@@ -2212,7 +2215,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2212 | if (error) | 2215 | if (error) |
2213 | return error; | 2216 | return error; |
2214 | 2217 | ||
2215 | if (!dir->i_op || !dir->i_op->unlink) | 2218 | if (!dir->i_op->unlink) |
2216 | return -EPERM; | 2219 | return -EPERM; |
2217 | 2220 | ||
2218 | DQUOT_INIT(dir); | 2221 | DQUOT_INIT(dir); |
@@ -2273,7 +2276,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2273 | error = mnt_want_write(nd.path.mnt); | 2276 | error = mnt_want_write(nd.path.mnt); |
2274 | if (error) | 2277 | if (error) |
2275 | goto exit2; | 2278 | goto exit2; |
2279 | error = security_path_unlink(&nd.path, dentry); | ||
2280 | if (error) | ||
2281 | goto exit3; | ||
2276 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2282 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2283 | exit3: | ||
2277 | mnt_drop_write(nd.path.mnt); | 2284 | mnt_drop_write(nd.path.mnt); |
2278 | exit2: | 2285 | exit2: |
2279 | dput(dentry); | 2286 | dput(dentry); |
@@ -2292,7 +2299,7 @@ slashes: | |||
2292 | goto exit2; | 2299 | goto exit2; |
2293 | } | 2300 | } |
2294 | 2301 | ||
2295 | asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag) | 2302 | SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) |
2296 | { | 2303 | { |
2297 | if ((flag & ~AT_REMOVEDIR) != 0) | 2304 | if ((flag & ~AT_REMOVEDIR) != 0) |
2298 | return -EINVAL; | 2305 | return -EINVAL; |
@@ -2303,7 +2310,7 @@ asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag) | |||
2303 | return do_unlinkat(dfd, pathname); | 2310 | return do_unlinkat(dfd, pathname); |
2304 | } | 2311 | } |
2305 | 2312 | ||
2306 | asmlinkage long sys_unlink(const char __user *pathname) | 2313 | SYSCALL_DEFINE1(unlink, const char __user *, pathname) |
2307 | { | 2314 | { |
2308 | return do_unlinkat(AT_FDCWD, pathname); | 2315 | return do_unlinkat(AT_FDCWD, pathname); |
2309 | } | 2316 | } |
@@ -2315,7 +2322,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | |||
2315 | if (error) | 2322 | if (error) |
2316 | return error; | 2323 | return error; |
2317 | 2324 | ||
2318 | if (!dir->i_op || !dir->i_op->symlink) | 2325 | if (!dir->i_op->symlink) |
2319 | return -EPERM; | 2326 | return -EPERM; |
2320 | 2327 | ||
2321 | error = security_inode_symlink(dir, dentry, oldname); | 2328 | error = security_inode_symlink(dir, dentry, oldname); |
@@ -2329,8 +2336,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | |||
2329 | return error; | 2336 | return error; |
2330 | } | 2337 | } |
2331 | 2338 | ||
2332 | asmlinkage long sys_symlinkat(const char __user *oldname, | 2339 | SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, |
2333 | int newdfd, const char __user *newname) | 2340 | int, newdfd, const char __user *, newname) |
2334 | { | 2341 | { |
2335 | int error; | 2342 | int error; |
2336 | char *from; | 2343 | char *from; |
@@ -2354,7 +2361,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2354 | error = mnt_want_write(nd.path.mnt); | 2361 | error = mnt_want_write(nd.path.mnt); |
2355 | if (error) | 2362 | if (error) |
2356 | goto out_dput; | 2363 | goto out_dput; |
2364 | error = security_path_symlink(&nd.path, dentry, from); | ||
2365 | if (error) | ||
2366 | goto out_drop_write; | ||
2357 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2367 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
2368 | out_drop_write: | ||
2358 | mnt_drop_write(nd.path.mnt); | 2369 | mnt_drop_write(nd.path.mnt); |
2359 | out_dput: | 2370 | out_dput: |
2360 | dput(dentry); | 2371 | dput(dentry); |
@@ -2367,7 +2378,7 @@ out_putname: | |||
2367 | return error; | 2378 | return error; |
2368 | } | 2379 | } |
2369 | 2380 | ||
2370 | asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname) | 2381 | SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newname) |
2371 | { | 2382 | { |
2372 | return sys_symlinkat(oldname, AT_FDCWD, newname); | 2383 | return sys_symlinkat(oldname, AT_FDCWD, newname); |
2373 | } | 2384 | } |
@@ -2392,7 +2403,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2392 | */ | 2403 | */ |
2393 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 2404 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
2394 | return -EPERM; | 2405 | return -EPERM; |
2395 | if (!dir->i_op || !dir->i_op->link) | 2406 | if (!dir->i_op->link) |
2396 | return -EPERM; | 2407 | return -EPERM; |
2397 | if (S_ISDIR(inode->i_mode)) | 2408 | if (S_ISDIR(inode->i_mode)) |
2398 | return -EPERM; | 2409 | return -EPERM; |
@@ -2419,9 +2430,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2419 | * with linux 2.0, and to avoid hard-linking to directories | 2430 | * with linux 2.0, and to avoid hard-linking to directories |
2420 | * and other special files. --ADM | 2431 | * and other special files. --ADM |
2421 | */ | 2432 | */ |
2422 | asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | 2433 | SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, |
2423 | int newdfd, const char __user *newname, | 2434 | int, newdfd, const char __user *, newname, int, flags) |
2424 | int flags) | ||
2425 | { | 2435 | { |
2426 | struct dentry *new_dentry; | 2436 | struct dentry *new_dentry; |
2427 | struct nameidata nd; | 2437 | struct nameidata nd; |
@@ -2451,7 +2461,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2451 | error = mnt_want_write(nd.path.mnt); | 2461 | error = mnt_want_write(nd.path.mnt); |
2452 | if (error) | 2462 | if (error) |
2453 | goto out_dput; | 2463 | goto out_dput; |
2464 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
2465 | if (error) | ||
2466 | goto out_drop_write; | ||
2454 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2467 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
2468 | out_drop_write: | ||
2455 | mnt_drop_write(nd.path.mnt); | 2469 | mnt_drop_write(nd.path.mnt); |
2456 | out_dput: | 2470 | out_dput: |
2457 | dput(new_dentry); | 2471 | dput(new_dentry); |
@@ -2466,7 +2480,7 @@ out: | |||
2466 | return error; | 2480 | return error; |
2467 | } | 2481 | } |
2468 | 2482 | ||
2469 | asmlinkage long sys_link(const char __user *oldname, const char __user *newname) | 2483 | SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname) |
2470 | { | 2484 | { |
2471 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); | 2485 | return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
2472 | } | 2486 | } |
@@ -2595,7 +2609,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2595 | if (error) | 2609 | if (error) |
2596 | return error; | 2610 | return error; |
2597 | 2611 | ||
2598 | if (!old_dir->i_op || !old_dir->i_op->rename) | 2612 | if (!old_dir->i_op->rename) |
2599 | return -EPERM; | 2613 | return -EPERM; |
2600 | 2614 | ||
2601 | DQUOT_INIT(old_dir); | 2615 | DQUOT_INIT(old_dir); |
@@ -2617,8 +2631,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2617 | return error; | 2631 | return error; |
2618 | } | 2632 | } |
2619 | 2633 | ||
2620 | asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | 2634 | SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, |
2621 | int newdfd, const char __user *newname) | 2635 | int, newdfd, const char __user *, newname) |
2622 | { | 2636 | { |
2623 | struct dentry *old_dir, *new_dir; | 2637 | struct dentry *old_dir, *new_dir; |
2624 | struct dentry *old_dentry, *new_dentry; | 2638 | struct dentry *old_dentry, *new_dentry; |
@@ -2687,8 +2701,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
2687 | error = mnt_want_write(oldnd.path.mnt); | 2701 | error = mnt_want_write(oldnd.path.mnt); |
2688 | if (error) | 2702 | if (error) |
2689 | goto exit5; | 2703 | goto exit5; |
2704 | error = security_path_rename(&oldnd.path, old_dentry, | ||
2705 | &newnd.path, new_dentry); | ||
2706 | if (error) | ||
2707 | goto exit6; | ||
2690 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2708 | error = vfs_rename(old_dir->d_inode, old_dentry, |
2691 | new_dir->d_inode, new_dentry); | 2709 | new_dir->d_inode, new_dentry); |
2710 | exit6: | ||
2692 | mnt_drop_write(oldnd.path.mnt); | 2711 | mnt_drop_write(oldnd.path.mnt); |
2693 | exit5: | 2712 | exit5: |
2694 | dput(new_dentry); | 2713 | dput(new_dentry); |
@@ -2706,7 +2725,7 @@ exit: | |||
2706 | return error; | 2725 | return error; |
2707 | } | 2726 | } |
2708 | 2727 | ||
2709 | asmlinkage long sys_rename(const char __user *oldname, const char __user *newname) | 2728 | SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) |
2710 | { | 2729 | { |
2711 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); | 2730 | return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname); |
2712 | } | 2731 | } |
@@ -2758,13 +2777,16 @@ int vfs_follow_link(struct nameidata *nd, const char *link) | |||
2758 | /* get the link contents into pagecache */ | 2777 | /* get the link contents into pagecache */ |
2759 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 2778 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
2760 | { | 2779 | { |
2761 | struct page * page; | 2780 | char *kaddr; |
2781 | struct page *page; | ||
2762 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2782 | struct address_space *mapping = dentry->d_inode->i_mapping; |
2763 | page = read_mapping_page(mapping, 0, NULL); | 2783 | page = read_mapping_page(mapping, 0, NULL); |
2764 | if (IS_ERR(page)) | 2784 | if (IS_ERR(page)) |
2765 | return (char*)page; | 2785 | return (char*)page; |
2766 | *ppage = page; | 2786 | *ppage = page; |
2767 | return kmap(page); | 2787 | kaddr = kmap(page); |
2788 | nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); | ||
2789 | return kaddr; | ||
2768 | } | 2790 | } |
2769 | 2791 | ||
2770 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2792 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
@@ -2796,18 +2818,23 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | |||
2796 | } | 2818 | } |
2797 | } | 2819 | } |
2798 | 2820 | ||
2799 | int __page_symlink(struct inode *inode, const char *symname, int len, | 2821 | /* |
2800 | gfp_t gfp_mask) | 2822 | * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS |
2823 | */ | ||
2824 | int __page_symlink(struct inode *inode, const char *symname, int len, int nofs) | ||
2801 | { | 2825 | { |
2802 | struct address_space *mapping = inode->i_mapping; | 2826 | struct address_space *mapping = inode->i_mapping; |
2803 | struct page *page; | 2827 | struct page *page; |
2804 | void *fsdata; | 2828 | void *fsdata; |
2805 | int err; | 2829 | int err; |
2806 | char *kaddr; | 2830 | char *kaddr; |
2831 | unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE; | ||
2832 | if (nofs) | ||
2833 | flags |= AOP_FLAG_NOFS; | ||
2807 | 2834 | ||
2808 | retry: | 2835 | retry: |
2809 | err = pagecache_write_begin(NULL, mapping, 0, len-1, | 2836 | err = pagecache_write_begin(NULL, mapping, 0, len-1, |
2810 | AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata); | 2837 | flags, &page, &fsdata); |
2811 | if (err) | 2838 | if (err) |
2812 | goto fail; | 2839 | goto fail; |
2813 | 2840 | ||
@@ -2831,7 +2858,7 @@ fail: | |||
2831 | int page_symlink(struct inode *inode, const char *symname, int len) | 2858 | int page_symlink(struct inode *inode, const char *symname, int len) |
2832 | { | 2859 | { |
2833 | return __page_symlink(inode, symname, len, | 2860 | return __page_symlink(inode, symname, len, |
2834 | mapping_gfp_mask(inode->i_mapping)); | 2861 | !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS)); |
2835 | } | 2862 | } |
2836 | 2863 | ||
2837 | const struct inode_operations page_symlink_inode_operations = { | 2864 | const struct inode_operations page_symlink_inode_operations = { |
@@ -2857,7 +2884,6 @@ EXPORT_SYMBOL(path_lookup); | |||
2857 | EXPORT_SYMBOL(kern_path); | 2884 | EXPORT_SYMBOL(kern_path); |
2858 | EXPORT_SYMBOL(vfs_path_lookup); | 2885 | EXPORT_SYMBOL(vfs_path_lookup); |
2859 | EXPORT_SYMBOL(inode_permission); | 2886 | EXPORT_SYMBOL(inode_permission); |
2860 | EXPORT_SYMBOL(vfs_permission); | ||
2861 | EXPORT_SYMBOL(file_permission); | 2887 | EXPORT_SYMBOL(file_permission); |
2862 | EXPORT_SYMBOL(unlock_rename); | 2888 | EXPORT_SYMBOL(unlock_rename); |
2863 | EXPORT_SYMBOL(vfs_create); | 2889 | EXPORT_SYMBOL(vfs_create); |
@@ -2873,3 +2899,10 @@ EXPORT_SYMBOL(vfs_symlink); | |||
2873 | EXPORT_SYMBOL(vfs_unlink); | 2899 | EXPORT_SYMBOL(vfs_unlink); |
2874 | EXPORT_SYMBOL(dentry_unhash); | 2900 | EXPORT_SYMBOL(dentry_unhash); |
2875 | EXPORT_SYMBOL(generic_readlink); | 2901 | EXPORT_SYMBOL(generic_readlink); |
2902 | |||
2903 | /* to be mentioned only in INIT_TASK */ | ||
2904 | struct fs_struct init_fs = { | ||
2905 | .count = ATOMIC_INIT(1), | ||
2906 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
2907 | .umask = 0022, | ||
2908 | }; | ||