diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2016-06-09 16:32:10 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2016-06-23 16:41:54 -0400 |
commit | e94591d0d90c13166cb6eb54ce5f96ed13d81b55 (patch) | |
tree | a52df89fe96d5ed24657c3fed1552ffc1d474b3a /fs/proc | |
parent | d91ee87d8d85a0808c01787e8b4a6b48f2ba487b (diff) |
proc: Convert proc_mount to use mount_ns.
Move the call of get_pid_ns, the call of proc_parse_options, and
the setting of s_iflags into proc_fill_super so that mount_ns
can be used.
Convert proc_mount to call mount_ns and remove the now unnecessary
code.
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Reviewed-by: Djalal Harouni <tixxdz@gmail.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/inode.c | 9 | ||||
-rw-r--r-- | fs/proc/internal.h | 3 | ||||
-rw-r--r-- | fs/proc/root.c | 52 |
3 files changed, 13 insertions, 51 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 78fa452d65ed..f4817efb25a6 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -457,12 +457,17 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) | |||
457 | return inode; | 457 | return inode; |
458 | } | 458 | } |
459 | 459 | ||
460 | int proc_fill_super(struct super_block *s) | 460 | int proc_fill_super(struct super_block *s, void *data, int silent) |
461 | { | 461 | { |
462 | struct pid_namespace *ns = get_pid_ns(s->s_fs_info); | ||
462 | struct inode *root_inode; | 463 | struct inode *root_inode; |
463 | int ret; | 464 | int ret; |
464 | 465 | ||
465 | s->s_iflags |= SB_I_USERNS_VISIBLE; | 466 | if (!proc_parse_options(data, ns)) |
467 | return -EINVAL; | ||
468 | |||
469 | /* User space would break if executables appear on proc */ | ||
470 | s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC; | ||
466 | s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC; | 471 | s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC; |
467 | s->s_blocksize = 1024; | 472 | s->s_blocksize = 1024; |
468 | s->s_blocksize_bits = 10; | 473 | s->s_blocksize_bits = 10; |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index aa2781095bd1..7931c558c192 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -212,7 +212,7 @@ extern const struct inode_operations proc_pid_link_inode_operations; | |||
212 | 212 | ||
213 | extern void proc_init_inodecache(void); | 213 | extern void proc_init_inodecache(void); |
214 | extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); | 214 | extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); |
215 | extern int proc_fill_super(struct super_block *); | 215 | extern int proc_fill_super(struct super_block *, void *data, int flags); |
216 | extern void proc_entry_rundown(struct proc_dir_entry *); | 216 | extern void proc_entry_rundown(struct proc_dir_entry *); |
217 | 217 | ||
218 | /* | 218 | /* |
@@ -268,6 +268,7 @@ static inline void proc_tty_init(void) {} | |||
268 | * root.c | 268 | * root.c |
269 | */ | 269 | */ |
270 | extern struct proc_dir_entry proc_root; | 270 | extern struct proc_dir_entry proc_root; |
271 | extern int proc_parse_options(char *options, struct pid_namespace *pid); | ||
271 | 272 | ||
272 | extern void proc_self_init(void); | 273 | extern void proc_self_init(void); |
273 | extern int proc_remount(struct super_block *, int *, char *); | 274 | extern int proc_remount(struct super_block *, int *, char *); |
diff --git a/fs/proc/root.c b/fs/proc/root.c index a1b2860fec62..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,45 +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 | if (!proc_parse_options(options, ns)) { | ||
125 | deactivate_locked_super(sb); | ||
126 | return ERR_PTR(-EINVAL); | ||
127 | } | ||
128 | |||
129 | if (!sb->s_root) { | ||
130 | err = proc_fill_super(sb); | ||
131 | if (err) { | ||
132 | deactivate_locked_super(sb); | ||
133 | return ERR_PTR(err); | ||
134 | } | ||
135 | |||
136 | sb->s_flags |= MS_ACTIVE; | ||
137 | /* User space would break if executables appear on proc */ | ||
138 | sb->s_iflags |= SB_I_NOEXEC; | ||
139 | } | 95 | } |
140 | 96 | ||
141 | return dget(sb->s_root); | 97 | return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super); |
142 | } | 98 | } |
143 | 99 | ||
144 | static void proc_kill_sb(struct super_block *sb) | 100 | static void proc_kill_sb(struct super_block *sb) |