diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 11:32:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 11:32:11 -0400 |
commit | 6c5daf012c9155aafd2c7973e4278766c30dfad0 (patch) | |
tree | 33959d7b36d03e1610615641a2940cb2de5e8603 /fs/namespace.c | |
parent | 6d39b27f0ac7e805ae3bd9efa51d7da04bec0360 (diff) | |
parent | c08d3b0e33edce28e9cfa7b64f7fe5bdeeb29248 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
truncate: use new helpers
truncate: new helpers
fs: fix overflow in sys_mount() for in-kernel calls
fs: Make unload_nls() NULL pointer safe
freeze_bdev: grab active reference to frozen superblocks
freeze_bdev: kill bd_mount_sem
exofs: remove BKL from super operations
fs/romfs: correct error-handling code
vfs: seq_file: add helpers for data filling
vfs: remove redundant position check in do_sendfile
vfs: change sb->s_maxbytes to a loff_t
vfs: explicitly cast s_maxbytes in fiemap_check_ranges
libfs: return error code on failed attr set
seq_file: return a negative error code when seq_path_root() fails.
vfs: optimize touch_time() too
vfs: optimization for touch_atime()
vfs: split generic_forget_inode() so that hugetlbfs does not have to copy it
fs/inode.c: add dev-id and inode number for debugging in init_special_inode()
libfs: make simple_read_from_buffer conventional
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 77 |
1 files changed, 47 insertions, 30 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 7230787d18b0..bdc3cb4fd222 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1640,7 +1640,7 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1640 | { | 1640 | { |
1641 | struct vfsmount *mnt; | 1641 | struct vfsmount *mnt; |
1642 | 1642 | ||
1643 | if (!type || !memchr(type, 0, PAGE_SIZE)) | 1643 | if (!type) |
1644 | return -EINVAL; | 1644 | return -EINVAL; |
1645 | 1645 | ||
1646 | /* we need capabilities... */ | 1646 | /* we need capabilities... */ |
@@ -1871,6 +1871,23 @@ int copy_mount_options(const void __user * data, unsigned long *where) | |||
1871 | return 0; | 1871 | return 0; |
1872 | } | 1872 | } |
1873 | 1873 | ||
1874 | int copy_mount_string(const void __user *data, char **where) | ||
1875 | { | ||
1876 | char *tmp; | ||
1877 | |||
1878 | if (!data) { | ||
1879 | *where = NULL; | ||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | tmp = strndup_user(data, PAGE_SIZE); | ||
1884 | if (IS_ERR(tmp)) | ||
1885 | return PTR_ERR(tmp); | ||
1886 | |||
1887 | *where = tmp; | ||
1888 | return 0; | ||
1889 | } | ||
1890 | |||
1874 | /* | 1891 | /* |
1875 | * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to | 1892 | * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to |
1876 | * be given to the mount() call (ie: read-only, no-dev, no-suid etc). | 1893 | * be given to the mount() call (ie: read-only, no-dev, no-suid etc). |
@@ -1900,8 +1917,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1900 | 1917 | ||
1901 | if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) | 1918 | if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) |
1902 | return -EINVAL; | 1919 | return -EINVAL; |
1903 | if (dev_name && !memchr(dev_name, 0, PAGE_SIZE)) | ||
1904 | return -EINVAL; | ||
1905 | 1920 | ||
1906 | if (data_page) | 1921 | if (data_page) |
1907 | ((char *)data_page)[PAGE_SIZE - 1] = 0; | 1922 | ((char *)data_page)[PAGE_SIZE - 1] = 0; |
@@ -2070,40 +2085,42 @@ EXPORT_SYMBOL(create_mnt_ns); | |||
2070 | SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | 2085 | SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, |
2071 | char __user *, type, unsigned long, flags, void __user *, data) | 2086 | char __user *, type, unsigned long, flags, void __user *, data) |
2072 | { | 2087 | { |
2073 | int retval; | 2088 | int ret; |
2089 | char *kernel_type; | ||
2090 | char *kernel_dir; | ||
2091 | char *kernel_dev; | ||
2074 | unsigned long data_page; | 2092 | unsigned long data_page; |
2075 | unsigned long type_page; | ||
2076 | unsigned long dev_page; | ||
2077 | char *dir_page; | ||
2078 | 2093 | ||
2079 | retval = copy_mount_options(type, &type_page); | 2094 | ret = copy_mount_string(type, &kernel_type); |
2080 | if (retval < 0) | 2095 | if (ret < 0) |
2081 | return retval; | 2096 | goto out_type; |
2082 | 2097 | ||
2083 | dir_page = getname(dir_name); | 2098 | kernel_dir = getname(dir_name); |
2084 | retval = PTR_ERR(dir_page); | 2099 | if (IS_ERR(kernel_dir)) { |
2085 | if (IS_ERR(dir_page)) | 2100 | ret = PTR_ERR(kernel_dir); |
2086 | goto out1; | 2101 | goto out_dir; |
2102 | } | ||
2087 | 2103 | ||
2088 | retval = copy_mount_options(dev_name, &dev_page); | 2104 | ret = copy_mount_string(dev_name, &kernel_dev); |
2089 | if (retval < 0) | 2105 | if (ret < 0) |
2090 | goto out2; | 2106 | goto out_dev; |
2091 | 2107 | ||
2092 | retval = copy_mount_options(data, &data_page); | 2108 | ret = copy_mount_options(data, &data_page); |
2093 | if (retval < 0) | 2109 | if (ret < 0) |
2094 | goto out3; | 2110 | goto out_data; |
2095 | 2111 | ||
2096 | retval = do_mount((char *)dev_page, dir_page, (char *)type_page, | 2112 | ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags, |
2097 | flags, (void *)data_page); | 2113 | (void *) data_page); |
2098 | free_page(data_page); | ||
2099 | 2114 | ||
2100 | out3: | 2115 | free_page(data_page); |
2101 | free_page(dev_page); | 2116 | out_data: |
2102 | out2: | 2117 | kfree(kernel_dev); |
2103 | putname(dir_page); | 2118 | out_dev: |
2104 | out1: | 2119 | putname(kernel_dir); |
2105 | free_page(type_page); | 2120 | out_dir: |
2106 | return retval; | 2121 | kfree(kernel_type); |
2122 | out_type: | ||
2123 | return ret; | ||
2107 | } | 2124 | } |
2108 | 2125 | ||
2109 | /* | 2126 | /* |