Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
root.c
Go to the documentation of this file.
1 /*
2  * linux/fs/proc/root.c
3  *
4  * Copyright (C) 1991, 1992 Linus Torvalds
5  *
6  * proc root directory handling functions
7  */
8 
9 #include <asm/uaccess.h>
10 
11 #include <linux/errno.h>
12 #include <linux/time.h>
13 #include <linux/proc_fs.h>
14 #include <linux/stat.h>
15 #include <linux/init.h>
16 #include <linux/sched.h>
17 #include <linux/module.h>
18 #include <linux/bitops.h>
19 #include <linux/mount.h>
20 #include <linux/pid_namespace.h>
21 #include <linux/parser.h>
22 
23 #include "internal.h"
24 
25 static int proc_test_super(struct super_block *sb, void *data)
26 {
27  return sb->s_fs_info == data;
28 }
29 
30 static int proc_set_super(struct super_block *sb, void *data)
31 {
32  int err = set_anon_super(sb, NULL);
33  if (!err) {
34  struct pid_namespace *ns = (struct pid_namespace *)data;
35  sb->s_fs_info = get_pid_ns(ns);
36  }
37  return err;
38 }
39 
40 enum {
42 };
43 
44 static const match_table_t tokens = {
45  {Opt_hidepid, "hidepid=%u"},
46  {Opt_gid, "gid=%u"},
47  {Opt_err, NULL},
48 };
49 
50 static int proc_parse_options(char *options, struct pid_namespace *pid)
51 {
52  char *p;
54  int option;
55 
56  if (!options)
57  return 1;
58 
59  while ((p = strsep(&options, ",")) != NULL) {
60  int token;
61  if (!*p)
62  continue;
63 
64  args[0].to = args[0].from = NULL;
65  token = match_token(p, tokens, args);
66  switch (token) {
67  case Opt_gid:
68  if (match_int(&args[0], &option))
69  return 0;
70  pid->pid_gid = make_kgid(current_user_ns(), option);
71  break;
72  case Opt_hidepid:
73  if (match_int(&args[0], &option))
74  return 0;
75  if (option < 0 || option > 2) {
76  pr_err("proc: hidepid value must be between 0 and 2.\n");
77  return 0;
78  }
79  pid->hide_pid = option;
80  break;
81  default:
82  pr_err("proc: unrecognized mount option \"%s\" "
83  "or missing value\n", p);
84  return 0;
85  }
86  }
87 
88  return 1;
89 }
90 
91 int proc_remount(struct super_block *sb, int *flags, char *data)
92 {
93  struct pid_namespace *pid = sb->s_fs_info;
94  return !proc_parse_options(data, pid);
95 }
96 
97 static struct dentry *proc_mount(struct file_system_type *fs_type,
98  int flags, const char *dev_name, void *data)
99 {
100  int err;
101  struct super_block *sb;
102  struct pid_namespace *ns;
103  struct proc_inode *ei;
104  char *options;
105 
106  if (flags & MS_KERNMOUNT) {
107  ns = (struct pid_namespace *)data;
108  options = NULL;
109  } else {
110  ns = current->nsproxy->pid_ns;
111  options = data;
112  }
113 
114  sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
115  if (IS_ERR(sb))
116  return ERR_CAST(sb);
117 
118  if (!proc_parse_options(options, ns)) {
120  return ERR_PTR(-EINVAL);
121  }
122 
123  if (!sb->s_root) {
124  err = proc_fill_super(sb);
125  if (err) {
127  return ERR_PTR(err);
128  }
129 
130  sb->s_flags |= MS_ACTIVE;
131  }
132 
133  ei = PROC_I(sb->s_root->d_inode);
134  if (!ei->pid) {
135  rcu_read_lock();
136  ei->pid = get_pid(find_pid_ns(1, ns));
137  rcu_read_unlock();
138  }
139 
140  return dget(sb->s_root);
141 }
142 
143 static void proc_kill_sb(struct super_block *sb)
144 {
145  struct pid_namespace *ns;
146 
147  ns = (struct pid_namespace *)sb->s_fs_info;
148  kill_anon_super(sb);
149  put_pid_ns(ns);
150 }
151 
152 static struct file_system_type proc_fs_type = {
153  .name = "proc",
154  .mount = proc_mount,
155  .kill_sb = proc_kill_sb,
156 };
157 
159 {
160  int err;
161 
163  err = register_filesystem(&proc_fs_type);
164  if (err)
165  return;
167  if (err) {
168  unregister_filesystem(&proc_fs_type);
169  return;
170  }
171 
172  proc_symlink("mounts", NULL, "self/mounts");
173 
174  proc_net_init();
175 
176 #ifdef CONFIG_SYSVIPC
177  proc_mkdir("sysvipc", NULL);
178 #endif
179  proc_mkdir("fs", NULL);
180  proc_mkdir("driver", NULL);
181  proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
182 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
183  /* just give it a mountpoint */
184  proc_mkdir("openprom", NULL);
185 #endif
186  proc_tty_init();
187 #ifdef CONFIG_PROC_DEVICETREE
189 #endif
190  proc_mkdir("bus", NULL);
191  proc_sys_init();
192 }
193 
194 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
195 )
196 {
197  generic_fillattr(dentry->d_inode, stat);
198  stat->nlink = proc_root.nlink + nr_processes();
199  return 0;
200 }
201 
202 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
203 {
204  if (!proc_lookup(dir, dentry, flags))
205  return NULL;
206 
207  return proc_pid_lookup(dir, dentry, flags);
208 }
209 
210 static int proc_root_readdir(struct file * filp,
211  void * dirent, filldir_t filldir)
212 {
213  unsigned int nr = filp->f_pos;
214  int ret;
215 
216  if (nr < FIRST_PROCESS_ENTRY) {
217  int error = proc_readdir(filp, dirent, filldir);
218  if (error <= 0)
219  return error;
220  filp->f_pos = FIRST_PROCESS_ENTRY;
221  }
222 
223  ret = proc_pid_readdir(filp, dirent, filldir);
224  return ret;
225 }
226 
227 /*
228  * The root /proc directory is special, as it has the
229  * <pid> directories. Thus we don't use the generic
230  * directory handling functions for that..
231  */
232 static const struct file_operations proc_root_operations = {
233  .read = generic_read_dir,
234  .readdir = proc_root_readdir,
235  .llseek = default_llseek,
236 };
237 
238 /*
239  * proc root can do almost nothing..
240  */
241 static const struct inode_operations proc_root_inode_operations = {
242  .lookup = proc_root_lookup,
243  .getattr = proc_root_getattr,
244 };
245 
246 /*
247  * This is the root "inode" in the /proc tree..
248  */
250  .low_ino = PROC_ROOT_INO,
251  .namelen = 5,
252  .mode = S_IFDIR | S_IRUGO | S_IXUGO,
253  .nlink = 2,
254  .count = ATOMIC_INIT(1),
255  .proc_iops = &proc_root_inode_operations,
256  .proc_fops = &proc_root_operations,
257  .parent = &proc_root,
258  .name = "/proc",
259 };
260 
262 {
263  struct vfsmount *mnt;
264 
265  mnt = kern_mount_data(&proc_fs_type, ns);
266  if (IS_ERR(mnt))
267  return PTR_ERR(mnt);
268 
269  ns->proc_mnt = mnt;
270  return 0;
271 }
272 
274 {
275  kern_unmount(ns->proc_mnt);
276 }