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