diff options
Diffstat (limited to 'fs/proc/root.c')
-rw-r--r-- | fs/proc/root.c | 61 |
1 files changed, 5 insertions, 56 deletions
diff --git a/fs/proc/root.c b/fs/proc/root.c index 06702783bf40..8d3e484055a6 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -23,21 +23,6 @@ | |||
23 | 23 | ||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | 25 | ||
26 | static int proc_test_super(struct super_block *sb, void *data) | ||
27 | { | ||
28 | return sb->s_fs_info == data; | ||
29 | } | ||
30 | |||
31 | static int proc_set_super(struct super_block *sb, void *data) | ||
32 | { | ||
33 | int err = set_anon_super(sb, NULL); | ||
34 | if (!err) { | ||
35 | struct pid_namespace *ns = (struct pid_namespace *)data; | ||
36 | sb->s_fs_info = get_pid_ns(ns); | ||
37 | } | ||
38 | return err; | ||
39 | } | ||
40 | |||
41 | enum { | 26 | enum { |
42 | Opt_gid, Opt_hidepid, Opt_err, | 27 | Opt_gid, Opt_hidepid, Opt_err, |
43 | }; | 28 | }; |
@@ -48,7 +33,7 @@ static const match_table_t tokens = { | |||
48 | {Opt_err, NULL}, | 33 | {Opt_err, NULL}, |
49 | }; | 34 | }; |
50 | 35 | ||
51 | static int proc_parse_options(char *options, struct pid_namespace *pid) | 36 | int proc_parse_options(char *options, struct pid_namespace *pid) |
52 | { | 37 | { |
53 | char *p; | 38 | char *p; |
54 | substring_t args[MAX_OPT_ARGS]; | 39 | substring_t args[MAX_OPT_ARGS]; |
@@ -100,52 +85,16 @@ int proc_remount(struct super_block *sb, int *flags, char *data) | |||
100 | static struct dentry *proc_mount(struct file_system_type *fs_type, | 85 | static struct dentry *proc_mount(struct file_system_type *fs_type, |
101 | int flags, const char *dev_name, void *data) | 86 | int flags, const char *dev_name, void *data) |
102 | { | 87 | { |
103 | int err; | ||
104 | struct super_block *sb; | ||
105 | struct pid_namespace *ns; | 88 | struct pid_namespace *ns; |
106 | char *options; | ||
107 | 89 | ||
108 | if (flags & MS_KERNMOUNT) { | 90 | if (flags & MS_KERNMOUNT) { |
109 | ns = (struct pid_namespace *)data; | 91 | ns = data; |
110 | options = NULL; | 92 | data = NULL; |
111 | } else { | 93 | } else { |
112 | ns = task_active_pid_ns(current); | 94 | ns = task_active_pid_ns(current); |
113 | options = data; | ||
114 | |||
115 | /* Does the mounter have privilege over the pid namespace? */ | ||
116 | if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) | ||
117 | return ERR_PTR(-EPERM); | ||
118 | } | ||
119 | |||
120 | sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns); | ||
121 | if (IS_ERR(sb)) | ||
122 | return ERR_CAST(sb); | ||
123 | |||
124 | /* | ||
125 | * procfs isn't actually a stacking filesystem; however, there is | ||
126 | * too much magic going on inside it to permit stacking things on | ||
127 | * top of it | ||
128 | */ | ||
129 | sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH; | ||
130 | |||
131 | if (!proc_parse_options(options, ns)) { | ||
132 | deactivate_locked_super(sb); | ||
133 | return ERR_PTR(-EINVAL); | ||
134 | } | ||
135 | |||
136 | if (!sb->s_root) { | ||
137 | err = proc_fill_super(sb); | ||
138 | if (err) { | ||
139 | deactivate_locked_super(sb); | ||
140 | return ERR_PTR(err); | ||
141 | } | ||
142 | |||
143 | sb->s_flags |= MS_ACTIVE; | ||
144 | /* User space would break if executables appear on proc */ | ||
145 | sb->s_iflags |= SB_I_NOEXEC; | ||
146 | } | 95 | } |
147 | 96 | ||
148 | return dget(sb->s_root); | 97 | return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super); |
149 | } | 98 | } |
150 | 99 | ||
151 | static void proc_kill_sb(struct super_block *sb) | 100 | static void proc_kill_sb(struct super_block *sb) |
@@ -165,7 +114,7 @@ static struct file_system_type proc_fs_type = { | |||
165 | .name = "proc", | 114 | .name = "proc", |
166 | .mount = proc_mount, | 115 | .mount = proc_mount, |
167 | .kill_sb = proc_kill_sb, | 116 | .kill_sb = proc_kill_sb, |
168 | .fs_flags = FS_USERNS_VISIBLE | FS_USERNS_MOUNT, | 117 | .fs_flags = FS_USERNS_MOUNT, |
169 | }; | 118 | }; |
170 | 119 | ||
171 | void __init proc_root_init(void) | 120 | void __init proc_root_init(void) |