aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 3dc283fd4716..bdc3cb4fd222 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -22,6 +22,7 @@
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/mnt_namespace.h> 23#include <linux/mnt_namespace.h>
24#include <linux/namei.h> 24#include <linux/namei.h>
25#include <linux/nsproxy.h>
25#include <linux/security.h> 26#include <linux/security.h>
26#include <linux/mount.h> 27#include <linux/mount.h>
27#include <linux/ramfs.h> 28#include <linux/ramfs.h>
@@ -315,7 +316,8 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
315 */ 316 */
316int mnt_want_write_file(struct file *file) 317int mnt_want_write_file(struct file *file)
317{ 318{
318 if (!(file->f_mode & FMODE_WRITE)) 319 struct inode *inode = file->f_dentry->d_inode;
320 if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
319 return mnt_want_write(file->f_path.mnt); 321 return mnt_want_write(file->f_path.mnt);
320 else 322 else
321 return mnt_clone_write(file->f_path.mnt); 323 return mnt_clone_write(file->f_path.mnt);
@@ -1638,7 +1640,7 @@ static int do_new_mount(struct path *path, char *type, int flags,
1638{ 1640{
1639 struct vfsmount *mnt; 1641 struct vfsmount *mnt;
1640 1642
1641 if (!type || !memchr(type, 0, PAGE_SIZE)) 1643 if (!type)
1642 return -EINVAL; 1644 return -EINVAL;
1643 1645
1644 /* we need capabilities... */ 1646 /* we need capabilities... */
@@ -1869,6 +1871,23 @@ int copy_mount_options(const void __user * data, unsigned long *where)
1869 return 0; 1871 return 0;
1870} 1872}
1871 1873
1874int 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
1872/* 1891/*
1873 * 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
1874 * 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).
@@ -1898,8 +1917,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
1898 1917
1899 if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) 1918 if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
1900 return -EINVAL; 1919 return -EINVAL;
1901 if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
1902 return -EINVAL;
1903 1920
1904 if (data_page) 1921 if (data_page)
1905 ((char *)data_page)[PAGE_SIZE - 1] = 0; 1922 ((char *)data_page)[PAGE_SIZE - 1] = 0;
@@ -2068,40 +2085,42 @@ EXPORT_SYMBOL(create_mnt_ns);
2068SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, 2085SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
2069 char __user *, type, unsigned long, flags, void __user *, data) 2086 char __user *, type, unsigned long, flags, void __user *, data)
2070{ 2087{
2071 int retval; 2088 int ret;
2089 char *kernel_type;
2090 char *kernel_dir;
2091 char *kernel_dev;
2072 unsigned long data_page; 2092 unsigned long data_page;
2073 unsigned long type_page;
2074 unsigned long dev_page;
2075 char *dir_page;
2076 2093
2077 retval = copy_mount_options(type, &type_page); 2094 ret = copy_mount_string(type, &kernel_type);
2078 if (retval < 0) 2095 if (ret < 0)
2079 return retval; 2096 goto out_type;
2080 2097
2081 dir_page = getname(dir_name); 2098 kernel_dir = getname(dir_name);
2082 retval = PTR_ERR(dir_page); 2099 if (IS_ERR(kernel_dir)) {
2083 if (IS_ERR(dir_page)) 2100 ret = PTR_ERR(kernel_dir);
2084 goto out1; 2101 goto out_dir;
2102 }
2085 2103
2086 retval = copy_mount_options(dev_name, &dev_page); 2104 ret = copy_mount_string(dev_name, &kernel_dev);
2087 if (retval < 0) 2105 if (ret < 0)
2088 goto out2; 2106 goto out_dev;
2089 2107
2090 retval = copy_mount_options(data, &data_page); 2108 ret = copy_mount_options(data, &data_page);
2091 if (retval < 0) 2109 if (ret < 0)
2092 goto out3; 2110 goto out_data;
2093 2111
2094 retval = do_mount((char *)dev_page, dir_page, (char *)type_page, 2112 ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
2095 flags, (void *)data_page); 2113 (void *) data_page);
2096 free_page(data_page);
2097 2114
2098out3: 2115 free_page(data_page);
2099 free_page(dev_page); 2116out_data:
2100out2: 2117 kfree(kernel_dev);
2101 putname(dir_page); 2118out_dev:
2102out1: 2119 putname(kernel_dir);
2103 free_page(type_page); 2120out_dir:
2104 return retval; 2121 kfree(kernel_type);
2122out_type:
2123 return ret;
2105} 2124}
2106 2125
2107/* 2126/*