Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * linux/fs/proc/root.c
4 : : *
5 : : * Copyright (C) 1991, 1992 Linus Torvalds
6 : : *
7 : : * proc root directory handling functions
8 : : */
9 : :
10 : : #include <linux/uaccess.h>
11 : :
12 : : #include <linux/errno.h>
13 : : #include <linux/time.h>
14 : : #include <linux/proc_fs.h>
15 : : #include <linux/stat.h>
16 : : #include <linux/init.h>
17 : : #include <linux/sched.h>
18 : : #include <linux/sched/stat.h>
19 : : #include <linux/module.h>
20 : : #include <linux/bitops.h>
21 : : #include <linux/user_namespace.h>
22 : : #include <linux/fs_context.h>
23 : : #include <linux/mount.h>
24 : : #include <linux/pid_namespace.h>
25 : : #include <linux/fs_parser.h>
26 : : #include <linux/cred.h>
27 : : #include <linux/magic.h>
28 : : #include <linux/slab.h>
29 : :
30 : : #include "internal.h"
31 : :
32 : : struct proc_fs_context {
33 : : struct pid_namespace *pid_ns;
34 : : unsigned int mask;
35 : : int hidepid;
36 : : int gid;
37 : : };
38 : :
39 : : enum proc_param {
40 : : Opt_gid,
41 : : Opt_hidepid,
42 : : };
43 : :
44 : : static const struct fs_parameter_spec proc_param_specs[] = {
45 : : fsparam_u32("gid", Opt_gid),
46 : : fsparam_u32("hidepid", Opt_hidepid),
47 : : {}
48 : : };
49 : :
50 : : static const struct fs_parameter_description proc_fs_parameters = {
51 : : .name = "proc",
52 : : .specs = proc_param_specs,
53 : : };
54 : :
55 : 414 : static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
56 : : {
57 : 414 : struct proc_fs_context *ctx = fc->fs_private;
58 : : struct fs_parse_result result;
59 : : int opt;
60 : :
61 : 414 : opt = fs_parse(fc, &proc_fs_parameters, param, &result);
62 [ - + ]: 414 : if (opt < 0)
63 : : return opt;
64 : :
65 [ # # # ]: 0 : switch (opt) {
66 : : case Opt_gid:
67 : 0 : ctx->gid = result.uint_32;
68 : 0 : break;
69 : :
70 : : case Opt_hidepid:
71 : 0 : ctx->hidepid = result.uint_32;
72 [ # # ]: 0 : if (ctx->hidepid < HIDEPID_OFF ||
73 : : ctx->hidepid > HIDEPID_INVISIBLE)
74 : 0 : return invalf(fc, "proc: hidepid value must be between 0 and 2.\n");
75 : : break;
76 : :
77 : : default:
78 : : return -EINVAL;
79 : : }
80 : :
81 : 0 : ctx->mask |= 1 << opt;
82 : 0 : return 0;
83 : : }
84 : :
85 : 414 : static void proc_apply_options(struct super_block *s,
86 : : struct fs_context *fc,
87 : : struct pid_namespace *pid_ns,
88 : : struct user_namespace *user_ns)
89 : : {
90 : 414 : struct proc_fs_context *ctx = fc->fs_private;
91 : :
92 [ - + ]: 414 : if (ctx->mask & (1 << Opt_gid))
93 : 0 : pid_ns->pid_gid = make_kgid(user_ns, ctx->gid);
94 [ - + ]: 414 : if (ctx->mask & (1 << Opt_hidepid))
95 : 0 : pid_ns->hide_pid = ctx->hidepid;
96 : 414 : }
97 : :
98 : 207 : static int proc_fill_super(struct super_block *s, struct fs_context *fc)
99 : : {
100 : 207 : struct pid_namespace *pid_ns = get_pid_ns(s->s_fs_info);
101 : : struct inode *root_inode;
102 : : int ret;
103 : :
104 : 207 : proc_apply_options(s, fc, pid_ns, current_user_ns());
105 : :
106 : : /* User space would break if executables or devices appear on proc */
107 : 207 : s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
108 : 207 : s->s_flags |= SB_NODIRATIME | SB_NOSUID | SB_NOEXEC;
109 : 207 : s->s_blocksize = 1024;
110 : 207 : s->s_blocksize_bits = 10;
111 : 207 : s->s_magic = PROC_SUPER_MAGIC;
112 : 207 : s->s_op = &proc_sops;
113 : 207 : s->s_time_gran = 1;
114 : :
115 : : /*
116 : : * procfs isn't actually a stacking filesystem; however, there is
117 : : * too much magic going on inside it to permit stacking things on
118 : : * top of it
119 : : */
120 : 207 : s->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
121 : :
122 : : /* procfs dentries and inodes don't require IO to create */
123 : 207 : s->s_shrink.seeks = 0;
124 : :
125 : : pde_get(&proc_root);
126 : 207 : root_inode = proc_get_inode(s, &proc_root);
127 [ - + ]: 207 : if (!root_inode) {
128 : 0 : pr_err("proc_fill_super: get root inode failed\n");
129 : 0 : return -ENOMEM;
130 : : }
131 : :
132 : 207 : s->s_root = d_make_root(root_inode);
133 [ - + ]: 207 : if (!s->s_root) {
134 : 0 : pr_err("proc_fill_super: allocate dentry failed\n");
135 : 0 : return -ENOMEM;
136 : : }
137 : :
138 : 207 : ret = proc_setup_self(s);
139 [ + - ]: 207 : if (ret) {
140 : : return ret;
141 : : }
142 : 207 : return proc_setup_thread_self(s);
143 : : }
144 : :
145 : 207 : static int proc_reconfigure(struct fs_context *fc)
146 : : {
147 : 207 : struct super_block *sb = fc->root->d_sb;
148 : 207 : struct pid_namespace *pid = sb->s_fs_info;
149 : :
150 : 207 : sync_filesystem(sb);
151 : :
152 : 207 : proc_apply_options(sb, fc, pid, current_user_ns());
153 : 207 : return 0;
154 : : }
155 : :
156 : 621 : static int proc_get_tree(struct fs_context *fc)
157 : : {
158 : 621 : struct proc_fs_context *ctx = fc->fs_private;
159 : :
160 : 621 : return get_tree_keyed(fc, proc_fill_super, ctx->pid_ns);
161 : : }
162 : :
163 : 828 : static void proc_fs_context_free(struct fs_context *fc)
164 : : {
165 : 828 : struct proc_fs_context *ctx = fc->fs_private;
166 : :
167 : 828 : put_pid_ns(ctx->pid_ns);
168 : 828 : kfree(ctx);
169 : 828 : }
170 : :
171 : : static const struct fs_context_operations proc_fs_context_ops = {
172 : : .free = proc_fs_context_free,
173 : : .parse_param = proc_parse_param,
174 : : .get_tree = proc_get_tree,
175 : : .reconfigure = proc_reconfigure,
176 : : };
177 : :
178 : 828 : static int proc_init_fs_context(struct fs_context *fc)
179 : : {
180 : : struct proc_fs_context *ctx;
181 : :
182 : 828 : ctx = kzalloc(sizeof(struct proc_fs_context), GFP_KERNEL);
183 [ + - ]: 828 : if (!ctx)
184 : : return -ENOMEM;
185 : :
186 : 1656 : ctx->pid_ns = get_pid_ns(task_active_pid_ns(current));
187 : 828 : put_user_ns(fc->user_ns);
188 : 828 : fc->user_ns = get_user_ns(ctx->pid_ns->user_ns);
189 : 828 : fc->fs_private = ctx;
190 : 828 : fc->ops = &proc_fs_context_ops;
191 : 828 : return 0;
192 : : }
193 : :
194 : 0 : static void proc_kill_sb(struct super_block *sb)
195 : : {
196 : : struct pid_namespace *ns;
197 : :
198 : 0 : ns = (struct pid_namespace *)sb->s_fs_info;
199 [ # # ]: 0 : if (ns->proc_self)
200 : 0 : dput(ns->proc_self);
201 [ # # ]: 0 : if (ns->proc_thread_self)
202 : 0 : dput(ns->proc_thread_self);
203 : 0 : kill_anon_super(sb);
204 : 0 : put_pid_ns(ns);
205 : 0 : }
206 : :
207 : : static struct file_system_type proc_fs_type = {
208 : : .name = "proc",
209 : : .init_fs_context = proc_init_fs_context,
210 : : .parameters = &proc_fs_parameters,
211 : : .kill_sb = proc_kill_sb,
212 : : .fs_flags = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM,
213 : : };
214 : :
215 : 207 : void __init proc_root_init(void)
216 : : {
217 : 207 : proc_init_kmemcache();
218 : 207 : set_proc_pid_nlink();
219 : 207 : proc_self_init();
220 : 207 : proc_thread_self_init();
221 : 207 : proc_symlink("mounts", NULL, "self/mounts");
222 : :
223 : 207 : proc_net_init();
224 : 207 : proc_mkdir("fs", NULL);
225 : 207 : proc_mkdir("driver", NULL);
226 : 207 : proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */
227 : : #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
228 : : /* just give it a mountpoint */
229 : : proc_create_mount_point("openprom");
230 : : #endif
231 : 207 : proc_tty_init();
232 : 207 : proc_mkdir("bus", NULL);
233 : 207 : proc_sys_init();
234 : :
235 : 207 : register_filesystem(&proc_fs_type);
236 : 207 : }
237 : :
238 : 11284 : static int proc_root_getattr(const struct path *path, struct kstat *stat,
239 : : u32 request_mask, unsigned int query_flags)
240 : : {
241 : 22568 : generic_fillattr(d_inode(path->dentry), stat);
242 : 11271 : stat->nlink = proc_root.nlink + nr_processes();
243 : 11284 : return 0;
244 : : }
245 : :
246 : 331401 : static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
247 : : {
248 [ + + ]: 331401 : if (!proc_pid_lookup(dentry, flags))
249 : : return NULL;
250 : :
251 : 23679 : return proc_lookup(dir, dentry, flags);
252 : : }
253 : :
254 : 0 : static int proc_root_readdir(struct file *file, struct dir_context *ctx)
255 : : {
256 [ # # ]: 0 : if (ctx->pos < FIRST_PROCESS_ENTRY) {
257 : 0 : int error = proc_readdir(file, ctx);
258 [ # # ]: 0 : if (unlikely(error <= 0))
259 : : return error;
260 : 0 : ctx->pos = FIRST_PROCESS_ENTRY;
261 : : }
262 : :
263 : 0 : return proc_pid_readdir(file, ctx);
264 : : }
265 : :
266 : : /*
267 : : * The root /proc directory is special, as it has the
268 : : * <pid> directories. Thus we don't use the generic
269 : : * directory handling functions for that..
270 : : */
271 : : static const struct file_operations proc_root_operations = {
272 : : .read = generic_read_dir,
273 : : .iterate_shared = proc_root_readdir,
274 : : .llseek = generic_file_llseek,
275 : : };
276 : :
277 : : /*
278 : : * proc root can do almost nothing..
279 : : */
280 : : static const struct inode_operations proc_root_inode_operations = {
281 : : .lookup = proc_root_lookup,
282 : : .getattr = proc_root_getattr,
283 : : };
284 : :
285 : : /*
286 : : * This is the root "inode" in the /proc tree..
287 : : */
288 : : struct proc_dir_entry proc_root = {
289 : : .low_ino = PROC_ROOT_INO,
290 : : .namelen = 5,
291 : : .mode = S_IFDIR | S_IRUGO | S_IXUGO,
292 : : .nlink = 2,
293 : : .refcnt = REFCOUNT_INIT(1),
294 : : .proc_iops = &proc_root_inode_operations,
295 : : .proc_fops = &proc_root_operations,
296 : : .parent = &proc_root,
297 : : .subdir = RB_ROOT,
298 : : .name = "/proc",
299 : : };
300 : :
301 : 207 : int pid_ns_prepare_proc(struct pid_namespace *ns)
302 : : {
303 : : struct proc_fs_context *ctx;
304 : : struct fs_context *fc;
305 : : struct vfsmount *mnt;
306 : :
307 : 207 : fc = fs_context_for_mount(&proc_fs_type, SB_KERNMOUNT);
308 [ - + ]: 207 : if (IS_ERR(fc))
309 : 0 : return PTR_ERR(fc);
310 : :
311 [ - + ]: 207 : if (fc->user_ns != ns->user_ns) {
312 : 0 : put_user_ns(fc->user_ns);
313 : 0 : fc->user_ns = get_user_ns(ns->user_ns);
314 : : }
315 : :
316 : 207 : ctx = fc->fs_private;
317 [ - + ]: 207 : if (ctx->pid_ns != ns) {
318 : 0 : put_pid_ns(ctx->pid_ns);
319 : : get_pid_ns(ns);
320 : 0 : ctx->pid_ns = ns;
321 : : }
322 : :
323 : 207 : mnt = fc_mount(fc);
324 : 207 : put_fs_context(fc);
325 [ - + ]: 207 : if (IS_ERR(mnt))
326 : 0 : return PTR_ERR(mnt);
327 : :
328 : 207 : ns->proc_mnt = mnt;
329 : 207 : return 0;
330 : : }
331 : :
332 : 0 : void pid_ns_release_proc(struct pid_namespace *ns)
333 : : {
334 : 0 : kern_unmount(ns->proc_mnt);
335 : 0 : }
|