xref: /openbmc/linux/fs/proc/root.c (revision a9a08845)
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/mount.h>
23  #include <linux/pid_namespace.h>
24  #include <linux/parser.h>
25  #include <linux/cred.h>
26  
27  #include "internal.h"
28  
29  enum {
30  	Opt_gid, Opt_hidepid, Opt_err,
31  };
32  
33  static const match_table_t tokens = {
34  	{Opt_hidepid, "hidepid=%u"},
35  	{Opt_gid, "gid=%u"},
36  	{Opt_err, NULL},
37  };
38  
39  int proc_parse_options(char *options, struct pid_namespace *pid)
40  {
41  	char *p;
42  	substring_t args[MAX_OPT_ARGS];
43  	int option;
44  
45  	if (!options)
46  		return 1;
47  
48  	while ((p = strsep(&options, ",")) != NULL) {
49  		int token;
50  		if (!*p)
51  			continue;
52  
53  		args[0].to = args[0].from = NULL;
54  		token = match_token(p, tokens, args);
55  		switch (token) {
56  		case Opt_gid:
57  			if (match_int(&args[0], &option))
58  				return 0;
59  			pid->pid_gid = make_kgid(current_user_ns(), option);
60  			break;
61  		case Opt_hidepid:
62  			if (match_int(&args[0], &option))
63  				return 0;
64  			if (option < HIDEPID_OFF ||
65  			    option > HIDEPID_INVISIBLE) {
66  				pr_err("proc: hidepid value must be between 0 and 2.\n");
67  				return 0;
68  			}
69  			pid->hide_pid = option;
70  			break;
71  		default:
72  			pr_err("proc: unrecognized mount option \"%s\" "
73  			       "or missing value\n", p);
74  			return 0;
75  		}
76  	}
77  
78  	return 1;
79  }
80  
81  int proc_remount(struct super_block *sb, int *flags, char *data)
82  {
83  	struct pid_namespace *pid = sb->s_fs_info;
84  
85  	sync_filesystem(sb);
86  	return !proc_parse_options(data, pid);
87  }
88  
89  static struct dentry *proc_mount(struct file_system_type *fs_type,
90  	int flags, const char *dev_name, void *data)
91  {
92  	struct pid_namespace *ns;
93  
94  	if (flags & SB_KERNMOUNT) {
95  		ns = data;
96  		data = NULL;
97  	} else {
98  		ns = task_active_pid_ns(current);
99  	}
100  
101  	return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super);
102  }
103  
104  static void proc_kill_sb(struct super_block *sb)
105  {
106  	struct pid_namespace *ns;
107  
108  	ns = (struct pid_namespace *)sb->s_fs_info;
109  	if (ns->proc_self)
110  		dput(ns->proc_self);
111  	if (ns->proc_thread_self)
112  		dput(ns->proc_thread_self);
113  	kill_anon_super(sb);
114  	put_pid_ns(ns);
115  }
116  
117  static struct file_system_type proc_fs_type = {
118  	.name		= "proc",
119  	.mount		= proc_mount,
120  	.kill_sb	= proc_kill_sb,
121  	.fs_flags	= FS_USERNS_MOUNT,
122  };
123  
124  void __init proc_root_init(void)
125  {
126  	int err;
127  
128  	proc_init_inodecache();
129  	set_proc_pid_nlink();
130  	err = register_filesystem(&proc_fs_type);
131  	if (err)
132  		return;
133  
134  	proc_self_init();
135  	proc_thread_self_init();
136  	proc_symlink("mounts", NULL, "self/mounts");
137  
138  	proc_net_init();
139  
140  #ifdef CONFIG_SYSVIPC
141  	proc_mkdir("sysvipc", NULL);
142  #endif
143  	proc_mkdir("fs", NULL);
144  	proc_mkdir("driver", NULL);
145  	proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */
146  #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
147  	/* just give it a mountpoint */
148  	proc_create_mount_point("openprom");
149  #endif
150  	proc_tty_init();
151  	proc_mkdir("bus", NULL);
152  	proc_sys_init();
153  }
154  
155  static int proc_root_getattr(const struct path *path, struct kstat *stat,
156  			     u32 request_mask, unsigned int query_flags)
157  {
158  	generic_fillattr(d_inode(path->dentry), stat);
159  	stat->nlink = proc_root.nlink + nr_processes();
160  	return 0;
161  }
162  
163  static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
164  {
165  	if (!proc_pid_lookup(dir, dentry, flags))
166  		return NULL;
167  
168  	return proc_lookup(dir, dentry, flags);
169  }
170  
171  static int proc_root_readdir(struct file *file, struct dir_context *ctx)
172  {
173  	if (ctx->pos < FIRST_PROCESS_ENTRY) {
174  		int error = proc_readdir(file, ctx);
175  		if (unlikely(error <= 0))
176  			return error;
177  		ctx->pos = FIRST_PROCESS_ENTRY;
178  	}
179  
180  	return proc_pid_readdir(file, ctx);
181  }
182  
183  /*
184   * The root /proc directory is special, as it has the
185   * <pid> directories. Thus we don't use the generic
186   * directory handling functions for that..
187   */
188  static const struct file_operations proc_root_operations = {
189  	.read		 = generic_read_dir,
190  	.iterate_shared	 = proc_root_readdir,
191  	.llseek		= generic_file_llseek,
192  };
193  
194  /*
195   * proc root can do almost nothing..
196   */
197  static const struct inode_operations proc_root_inode_operations = {
198  	.lookup		= proc_root_lookup,
199  	.getattr	= proc_root_getattr,
200  };
201  
202  /*
203   * This is the root "inode" in the /proc tree..
204   */
205  struct proc_dir_entry proc_root = {
206  	.low_ino	= PROC_ROOT_INO,
207  	.namelen	= 5,
208  	.mode		= S_IFDIR | S_IRUGO | S_IXUGO,
209  	.nlink		= 2,
210  	.count		= ATOMIC_INIT(1),
211  	.proc_iops	= &proc_root_inode_operations,
212  	.proc_fops	= &proc_root_operations,
213  	.parent		= &proc_root,
214  	.subdir		= RB_ROOT_CACHED,
215  	.name		= "/proc",
216  };
217  
218  int pid_ns_prepare_proc(struct pid_namespace *ns)
219  {
220  	struct vfsmount *mnt;
221  
222  	mnt = kern_mount_data(&proc_fs_type, ns);
223  	if (IS_ERR(mnt))
224  		return PTR_ERR(mnt);
225  
226  	ns->proc_mnt = mnt;
227  	return 0;
228  }
229  
230  void pid_ns_release_proc(struct pid_namespace *ns)
231  {
232  	kern_unmount(ns->proc_mnt);
233  }
234