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