xref: /openbmc/linux/fs/proc/proc_net.c (revision 5ff32883)
1 /*
2  *  linux/fs/proc/net.c
3  *
4  *  Copyright (C) 2007
5  *
6  *  Author: Eric Biederman <ebiederm@xmission.com>
7  *
8  *  proc net directory handling functions
9  */
10 
11 #include <linux/uaccess.h>
12 
13 #include <linux/errno.h>
14 #include <linux/time.h>
15 #include <linux/proc_fs.h>
16 #include <linux/stat.h>
17 #include <linux/slab.h>
18 #include <linux/init.h>
19 #include <linux/sched.h>
20 #include <linux/sched/task.h>
21 #include <linux/module.h>
22 #include <linux/bitops.h>
23 #include <linux/mount.h>
24 #include <linux/nsproxy.h>
25 #include <linux/uidgid.h>
26 #include <net/net_namespace.h>
27 #include <linux/seq_file.h>
28 
29 #include "internal.h"
30 
31 static inline struct net *PDE_NET(struct proc_dir_entry *pde)
32 {
33 	return pde->parent->data;
34 }
35 
36 static struct net *get_proc_net(const struct inode *inode)
37 {
38 	return maybe_get_net(PDE_NET(PDE(inode)));
39 }
40 
41 static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
42 {
43 	return 0;
44 }
45 
46 static const struct dentry_operations proc_net_dentry_ops = {
47 	.d_revalidate	= proc_net_d_revalidate,
48 	.d_delete	= always_delete_dentry,
49 };
50 
51 static void pde_force_lookup(struct proc_dir_entry *pde)
52 {
53 	/* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
54 	pde->proc_dops = &proc_net_dentry_ops;
55 }
56 
57 static int seq_open_net(struct inode *inode, struct file *file)
58 {
59 	unsigned int state_size = PDE(inode)->state_size;
60 	struct seq_net_private *p;
61 	struct net *net;
62 
63 	WARN_ON_ONCE(state_size < sizeof(*p));
64 
65 	if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
66 		return -EACCES;
67 
68 	net = get_proc_net(inode);
69 	if (!net)
70 		return -ENXIO;
71 
72 	p = __seq_open_private(file, PDE(inode)->seq_ops, state_size);
73 	if (!p) {
74 		put_net(net);
75 		return -ENOMEM;
76 	}
77 #ifdef CONFIG_NET_NS
78 	p->net = net;
79 #endif
80 	return 0;
81 }
82 
83 static int seq_release_net(struct inode *ino, struct file *f)
84 {
85 	struct seq_file *seq = f->private_data;
86 
87 	put_net(seq_file_net(seq));
88 	seq_release_private(ino, f);
89 	return 0;
90 }
91 
92 static const struct file_operations proc_net_seq_fops = {
93 	.open		= seq_open_net,
94 	.read		= seq_read,
95 	.write		= proc_simple_write,
96 	.llseek		= seq_lseek,
97 	.release	= seq_release_net,
98 };
99 
100 struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
101 		struct proc_dir_entry *parent, const struct seq_operations *ops,
102 		unsigned int state_size, void *data)
103 {
104 	struct proc_dir_entry *p;
105 
106 	p = proc_create_reg(name, mode, &parent, data);
107 	if (!p)
108 		return NULL;
109 	pde_force_lookup(p);
110 	p->proc_fops = &proc_net_seq_fops;
111 	p->seq_ops = ops;
112 	p->state_size = state_size;
113 	return proc_register(parent, p);
114 }
115 EXPORT_SYMBOL_GPL(proc_create_net_data);
116 
117 /**
118  * proc_create_net_data_write - Create a writable net_ns-specific proc file
119  * @name: The name of the file.
120  * @mode: The file's access mode.
121  * @parent: The parent directory in which to create.
122  * @ops: The seq_file ops with which to read the file.
123  * @write: The write method which which to 'modify' the file.
124  * @data: Data for retrieval by PDE_DATA().
125  *
126  * Create a network namespaced proc file in the @parent directory with the
127  * specified @name and @mode that allows reading of a file that displays a
128  * series of elements and also provides for the file accepting writes that have
129  * some arbitrary effect.
130  *
131  * The functions in the @ops table are used to iterate over items to be
132  * presented and extract the readable content using the seq_file interface.
133  *
134  * The @write function is called with the data copied into a kernel space
135  * scratch buffer and has a NUL appended for convenience.  The buffer may be
136  * modified by the @write function.  @write should return 0 on success.
137  *
138  * The @data value is accessible from the @show and @write functions by calling
139  * PDE_DATA() on the file inode.  The network namespace must be accessed by
140  * calling seq_file_net() on the seq_file struct.
141  */
142 struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
143 						  struct proc_dir_entry *parent,
144 						  const struct seq_operations *ops,
145 						  proc_write_t write,
146 						  unsigned int state_size, void *data)
147 {
148 	struct proc_dir_entry *p;
149 
150 	p = proc_create_reg(name, mode, &parent, data);
151 	if (!p)
152 		return NULL;
153 	pde_force_lookup(p);
154 	p->proc_fops = &proc_net_seq_fops;
155 	p->seq_ops = ops;
156 	p->state_size = state_size;
157 	p->write = write;
158 	return proc_register(parent, p);
159 }
160 EXPORT_SYMBOL_GPL(proc_create_net_data_write);
161 
162 static int single_open_net(struct inode *inode, struct file *file)
163 {
164 	struct proc_dir_entry *de = PDE(inode);
165 	struct net *net;
166 	int err;
167 
168 	net = get_proc_net(inode);
169 	if (!net)
170 		return -ENXIO;
171 
172 	err = single_open(file, de->single_show, net);
173 	if (err)
174 		put_net(net);
175 	return err;
176 }
177 
178 static int single_release_net(struct inode *ino, struct file *f)
179 {
180 	struct seq_file *seq = f->private_data;
181 	put_net(seq->private);
182 	return single_release(ino, f);
183 }
184 
185 static const struct file_operations proc_net_single_fops = {
186 	.open		= single_open_net,
187 	.read		= seq_read,
188 	.write		= proc_simple_write,
189 	.llseek		= seq_lseek,
190 	.release	= single_release_net,
191 };
192 
193 struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
194 		struct proc_dir_entry *parent,
195 		int (*show)(struct seq_file *, void *), void *data)
196 {
197 	struct proc_dir_entry *p;
198 
199 	p = proc_create_reg(name, mode, &parent, data);
200 	if (!p)
201 		return NULL;
202 	pde_force_lookup(p);
203 	p->proc_fops = &proc_net_single_fops;
204 	p->single_show = show;
205 	return proc_register(parent, p);
206 }
207 EXPORT_SYMBOL_GPL(proc_create_net_single);
208 
209 /**
210  * proc_create_net_single_write - Create a writable net_ns-specific proc file
211  * @name: The name of the file.
212  * @mode: The file's access mode.
213  * @parent: The parent directory in which to create.
214  * @show: The seqfile show method with which to read the file.
215  * @write: The write method which which to 'modify' the file.
216  * @data: Data for retrieval by PDE_DATA().
217  *
218  * Create a network-namespaced proc file in the @parent directory with the
219  * specified @name and @mode that allows reading of a file that displays a
220  * single element rather than a series and also provides for the file accepting
221  * writes that have some arbitrary effect.
222  *
223  * The @show function is called to extract the readable content via the
224  * seq_file interface.
225  *
226  * The @write function is called with the data copied into a kernel space
227  * scratch buffer and has a NUL appended for convenience.  The buffer may be
228  * modified by the @write function.  @write should return 0 on success.
229  *
230  * The @data value is accessible from the @show and @write functions by calling
231  * PDE_DATA() on the file inode.  The network namespace must be accessed by
232  * calling seq_file_single_net() on the seq_file struct.
233  */
234 struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
235 						    struct proc_dir_entry *parent,
236 						    int (*show)(struct seq_file *, void *),
237 						    proc_write_t write,
238 						    void *data)
239 {
240 	struct proc_dir_entry *p;
241 
242 	p = proc_create_reg(name, mode, &parent, data);
243 	if (!p)
244 		return NULL;
245 	pde_force_lookup(p);
246 	p->proc_fops = &proc_net_single_fops;
247 	p->single_show = show;
248 	p->write = write;
249 	return proc_register(parent, p);
250 }
251 EXPORT_SYMBOL_GPL(proc_create_net_single_write);
252 
253 static struct net *get_proc_task_net(struct inode *dir)
254 {
255 	struct task_struct *task;
256 	struct nsproxy *ns;
257 	struct net *net = NULL;
258 
259 	rcu_read_lock();
260 	task = pid_task(proc_pid(dir), PIDTYPE_PID);
261 	if (task != NULL) {
262 		task_lock(task);
263 		ns = task->nsproxy;
264 		if (ns != NULL)
265 			net = get_net(ns->net_ns);
266 		task_unlock(task);
267 	}
268 	rcu_read_unlock();
269 
270 	return net;
271 }
272 
273 static struct dentry *proc_tgid_net_lookup(struct inode *dir,
274 		struct dentry *dentry, unsigned int flags)
275 {
276 	struct dentry *de;
277 	struct net *net;
278 
279 	de = ERR_PTR(-ENOENT);
280 	net = get_proc_task_net(dir);
281 	if (net != NULL) {
282 		de = proc_lookup_de(dir, dentry, net->proc_net);
283 		put_net(net);
284 	}
285 	return de;
286 }
287 
288 static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat,
289 				 u32 request_mask, unsigned int query_flags)
290 {
291 	struct inode *inode = d_inode(path->dentry);
292 	struct net *net;
293 
294 	net = get_proc_task_net(inode);
295 
296 	generic_fillattr(inode, stat);
297 
298 	if (net != NULL) {
299 		stat->nlink = net->proc_net->nlink;
300 		put_net(net);
301 	}
302 
303 	return 0;
304 }
305 
306 const struct inode_operations proc_net_inode_operations = {
307 	.lookup		= proc_tgid_net_lookup,
308 	.getattr	= proc_tgid_net_getattr,
309 };
310 
311 static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)
312 {
313 	int ret;
314 	struct net *net;
315 
316 	ret = -EINVAL;
317 	net = get_proc_task_net(file_inode(file));
318 	if (net != NULL) {
319 		ret = proc_readdir_de(file, ctx, net->proc_net);
320 		put_net(net);
321 	}
322 	return ret;
323 }
324 
325 const struct file_operations proc_net_operations = {
326 	.llseek		= generic_file_llseek,
327 	.read		= generic_read_dir,
328 	.iterate_shared	= proc_tgid_net_readdir,
329 };
330 
331 static __net_init int proc_net_ns_init(struct net *net)
332 {
333 	struct proc_dir_entry *netd, *net_statd;
334 	kuid_t uid;
335 	kgid_t gid;
336 	int err;
337 
338 	err = -ENOMEM;
339 	netd = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
340 	if (!netd)
341 		goto out;
342 
343 	netd->subdir = RB_ROOT;
344 	netd->data = net;
345 	netd->nlink = 2;
346 	netd->namelen = 3;
347 	netd->parent = &proc_root;
348 	netd->name = netd->inline_name;
349 	memcpy(netd->name, "net", 4);
350 
351 	uid = make_kuid(net->user_ns, 0);
352 	if (!uid_valid(uid))
353 		uid = netd->uid;
354 
355 	gid = make_kgid(net->user_ns, 0);
356 	if (!gid_valid(gid))
357 		gid = netd->gid;
358 
359 	proc_set_user(netd, uid, gid);
360 
361 	err = -EEXIST;
362 	net_statd = proc_net_mkdir(net, "stat", netd);
363 	if (!net_statd)
364 		goto free_net;
365 
366 	net->proc_net = netd;
367 	net->proc_net_stat = net_statd;
368 	return 0;
369 
370 free_net:
371 	pde_free(netd);
372 out:
373 	return err;
374 }
375 
376 static __net_exit void proc_net_ns_exit(struct net *net)
377 {
378 	remove_proc_entry("stat", net->proc_net);
379 	pde_free(net->proc_net);
380 }
381 
382 static struct pernet_operations __net_initdata proc_net_ns_ops = {
383 	.init = proc_net_ns_init,
384 	.exit = proc_net_ns_exit,
385 };
386 
387 int __init proc_net_init(void)
388 {
389 	proc_symlink("net", NULL, "self/net");
390 
391 	return register_pernet_subsys(&proc_net_ns_ops);
392 }
393