diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namei.c | 93 | ||||
-rw-r--r-- | fs/open.c | 64 |
2 files changed, 87 insertions, 70 deletions
diff --git a/fs/namei.c b/fs/namei.c index 2892e68d3a86..7bdceedd254c 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1934,30 +1934,32 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
1934 | { | 1934 | { |
1935 | int error = 0; | 1935 | int error = 0; |
1936 | char * tmp; | 1936 | char * tmp; |
1937 | struct dentry *dentry; | ||
1938 | struct nameidata nd; | ||
1937 | 1939 | ||
1938 | tmp = getname(pathname); | 1940 | tmp = getname(pathname); |
1939 | error = PTR_ERR(tmp); | 1941 | error = PTR_ERR(tmp); |
1940 | if (!IS_ERR(tmp)) { | 1942 | if (IS_ERR(tmp)) |
1941 | struct dentry *dentry; | 1943 | goto out_err; |
1942 | struct nameidata nd; | ||
1943 | 1944 | ||
1944 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); | 1945 | error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); |
1945 | if (error) | 1946 | if (error) |
1946 | goto out; | 1947 | goto out; |
1947 | dentry = lookup_create(&nd, 1); | 1948 | dentry = lookup_create(&nd, 1); |
1948 | error = PTR_ERR(dentry); | 1949 | error = PTR_ERR(dentry); |
1949 | if (!IS_ERR(dentry)) { | 1950 | if (IS_ERR(dentry)) |
1950 | if (!IS_POSIXACL(nd.dentry->d_inode)) | 1951 | goto out_unlock; |
1951 | mode &= ~current->fs->umask; | ||
1952 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); | ||
1953 | dput(dentry); | ||
1954 | } | ||
1955 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | ||
1956 | path_release(&nd); | ||
1957 | out: | ||
1958 | putname(tmp); | ||
1959 | } | ||
1960 | 1952 | ||
1953 | if (!IS_POSIXACL(nd.dentry->d_inode)) | ||
1954 | mode &= ~current->fs->umask; | ||
1955 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); | ||
1956 | dput(dentry); | ||
1957 | out_unlock: | ||
1958 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | ||
1959 | path_release(&nd); | ||
1960 | out: | ||
1961 | putname(tmp); | ||
1962 | out_err: | ||
1961 | return error; | 1963 | return error; |
1962 | } | 1964 | } |
1963 | 1965 | ||
@@ -2056,10 +2058,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2056 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2058 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2057 | dentry = lookup_hash(&nd); | 2059 | dentry = lookup_hash(&nd); |
2058 | error = PTR_ERR(dentry); | 2060 | error = PTR_ERR(dentry); |
2059 | if (!IS_ERR(dentry)) { | 2061 | if (IS_ERR(dentry)) |
2060 | error = vfs_rmdir(nd.dentry->d_inode, dentry); | 2062 | goto exit2; |
2061 | dput(dentry); | 2063 | error = vfs_rmdir(nd.dentry->d_inode, dentry); |
2062 | } | 2064 | dput(dentry); |
2065 | exit2: | ||
2063 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2066 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2064 | exit1: | 2067 | exit1: |
2065 | path_release(&nd); | 2068 | path_release(&nd); |
@@ -2199,30 +2202,33 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2199 | int error = 0; | 2202 | int error = 0; |
2200 | char * from; | 2203 | char * from; |
2201 | char * to; | 2204 | char * to; |
2205 | struct dentry *dentry; | ||
2206 | struct nameidata nd; | ||
2202 | 2207 | ||
2203 | from = getname(oldname); | 2208 | from = getname(oldname); |
2204 | if(IS_ERR(from)) | 2209 | if(IS_ERR(from)) |
2205 | return PTR_ERR(from); | 2210 | return PTR_ERR(from); |
2206 | to = getname(newname); | 2211 | to = getname(newname); |
2207 | error = PTR_ERR(to); | 2212 | error = PTR_ERR(to); |
2208 | if (!IS_ERR(to)) { | 2213 | if (IS_ERR(to)) |
2209 | struct dentry *dentry; | 2214 | goto out_putname; |
2210 | struct nameidata nd; | ||
2211 | 2215 | ||
2212 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); | 2216 | error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); |
2213 | if (error) | 2217 | if (error) |
2214 | goto out; | 2218 | goto out; |
2215 | dentry = lookup_create(&nd, 0); | 2219 | dentry = lookup_create(&nd, 0); |
2216 | error = PTR_ERR(dentry); | 2220 | error = PTR_ERR(dentry); |
2217 | if (!IS_ERR(dentry)) { | 2221 | if (IS_ERR(dentry)) |
2218 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); | 2222 | goto out_unlock; |
2219 | dput(dentry); | 2223 | |
2220 | } | 2224 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); |
2221 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2225 | dput(dentry); |
2222 | path_release(&nd); | 2226 | out_unlock: |
2227 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | ||
2228 | path_release(&nd); | ||
2223 | out: | 2229 | out: |
2224 | putname(to); | 2230 | putname(to); |
2225 | } | 2231 | out_putname: |
2226 | putname(from); | 2232 | putname(from); |
2227 | return error; | 2233 | return error; |
2228 | } | 2234 | } |
@@ -2308,10 +2314,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2308 | goto out_release; | 2314 | goto out_release; |
2309 | new_dentry = lookup_create(&nd, 0); | 2315 | new_dentry = lookup_create(&nd, 0); |
2310 | error = PTR_ERR(new_dentry); | 2316 | error = PTR_ERR(new_dentry); |
2311 | if (!IS_ERR(new_dentry)) { | 2317 | if (IS_ERR(new_dentry)) |
2312 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); | 2318 | goto out_unlock; |
2313 | dput(new_dentry); | 2319 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); |
2314 | } | 2320 | dput(new_dentry); |
2321 | out_unlock: | ||
2315 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2322 | mutex_unlock(&nd.dentry->d_inode->i_mutex); |
2316 | out_release: | 2323 | out_release: |
2317 | path_release(&nd); | 2324 | path_release(&nd); |
@@ -386,15 +386,21 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
386 | current->cap_effective = current->cap_permitted; | 386 | current->cap_effective = current->cap_permitted; |
387 | 387 | ||
388 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); | 388 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); |
389 | if (!res) { | 389 | if (res) |
390 | res = vfs_permission(&nd, mode); | 390 | goto out; |
391 | /* SuS v2 requires we report a read only fs too */ | 391 | |
392 | if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) | 392 | res = vfs_permission(&nd, mode); |
393 | && !special_file(nd.dentry->d_inode->i_mode)) | 393 | /* SuS v2 requires we report a read only fs too */ |
394 | res = -EROFS; | 394 | if(res || !(mode & S_IWOTH) || |
395 | path_release(&nd); | 395 | special_file(nd.dentry->d_inode->i_mode)) |
396 | } | 396 | goto out_path_release; |
397 | |||
398 | if(IS_RDONLY(nd.dentry->d_inode)) | ||
399 | res = -EROFS; | ||
397 | 400 | ||
401 | out_path_release: | ||
402 | path_release(&nd); | ||
403 | out: | ||
398 | current->fsuid = old_fsuid; | 404 | current->fsuid = old_fsuid; |
399 | current->fsgid = old_fsgid; | 405 | current->fsgid = old_fsgid; |
400 | current->cap_effective = old_cap; | 406 | current->cap_effective = old_cap; |
@@ -603,10 +609,11 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) | |||
603 | int error; | 609 | int error; |
604 | 610 | ||
605 | error = user_path_walk(filename, &nd); | 611 | error = user_path_walk(filename, &nd); |
606 | if (!error) { | 612 | if (error) |
607 | error = chown_common(nd.dentry, user, group); | 613 | goto out; |
608 | path_release(&nd); | 614 | error = chown_common(nd.dentry, user, group); |
609 | } | 615 | path_release(&nd); |
616 | out: | ||
610 | return error; | 617 | return error; |
611 | } | 618 | } |
612 | 619 | ||
@@ -622,10 +629,10 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
622 | 629 | ||
623 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 630 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
624 | error = __user_walk_fd(dfd, filename, follow, &nd); | 631 | error = __user_walk_fd(dfd, filename, follow, &nd); |
625 | if (!error) { | 632 | if (error) |
626 | error = chown_common(nd.dentry, user, group); | 633 | goto out; |
627 | path_release(&nd); | 634 | error = chown_common(nd.dentry, user, group); |
628 | } | 635 | path_release(&nd); |
629 | out: | 636 | out: |
630 | return error; | 637 | return error; |
631 | } | 638 | } |
@@ -636,10 +643,11 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group | |||
636 | int error; | 643 | int error; |
637 | 644 | ||
638 | error = user_path_walk_link(filename, &nd); | 645 | error = user_path_walk_link(filename, &nd); |
639 | if (!error) { | 646 | if (error) |
640 | error = chown_common(nd.dentry, user, group); | 647 | goto out; |
641 | path_release(&nd); | 648 | error = chown_common(nd.dentry, user, group); |
642 | } | 649 | path_release(&nd); |
650 | out: | ||
643 | return error; | 651 | return error; |
644 | } | 652 | } |
645 | 653 | ||
@@ -648,15 +656,17 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
648 | { | 656 | { |
649 | struct file * file; | 657 | struct file * file; |
650 | int error = -EBADF; | 658 | int error = -EBADF; |
659 | struct dentry * dentry; | ||
651 | 660 | ||
652 | file = fget(fd); | 661 | file = fget(fd); |
653 | if (file) { | 662 | if (!file) |
654 | struct dentry * dentry; | 663 | goto out; |
655 | dentry = file->f_dentry; | 664 | |
656 | audit_inode(NULL, dentry->d_inode); | 665 | dentry = file->f_dentry; |
657 | error = chown_common(dentry, user, group); | 666 | audit_inode(NULL, dentry->d_inode); |
658 | fput(file); | 667 | error = chown_common(dentry, user, group); |
659 | } | 668 | fput(file); |
669 | out: | ||
660 | return error; | 670 | return error; |
661 | } | 671 | } |
662 | 672 | ||