aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/root.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/root.c')
-rw-r--r--fs/proc/root.c61
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
26static int proc_test_super(struct super_block *sb, void *data)
27{
28 return sb->s_fs_info == data;
29}
30
31static 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
41enum { 26enum {
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
51static int proc_parse_options(char *options, struct pid_namespace *pid) 36int 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)
100static struct dentry *proc_mount(struct file_system_type *fs_type, 85static 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
151static void proc_kill_sb(struct super_block *sb) 100static 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
171void __init proc_root_init(void) 120void __init proc_root_init(void)