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