xref: /openbmc/linux/fs/proc/proc_net.c (revision a86854d0)
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 seq_open_net(struct inode *inode, struct file *file)
42 {
43 	unsigned int state_size = PDE(inode)->state_size;
44 	struct seq_net_private *p;
45 	struct net *net;
46 
47 	WARN_ON_ONCE(state_size < sizeof(*p));
48 
49 	net = get_proc_net(inode);
50 	if (!net)
51 		return -ENXIO;
52 
53 	p = __seq_open_private(file, PDE(inode)->seq_ops, state_size);
54 	if (!p) {
55 		put_net(net);
56 		return -ENOMEM;
57 	}
58 #ifdef CONFIG_NET_NS
59 	p->net = net;
60 #endif
61 	return 0;
62 }
63 
64 static int seq_release_net(struct inode *ino, struct file *f)
65 {
66 	struct seq_file *seq = f->private_data;
67 
68 	put_net(seq_file_net(seq));
69 	seq_release_private(ino, f);
70 	return 0;
71 }
72 
73 static const struct file_operations proc_net_seq_fops = {
74 	.open		= seq_open_net,
75 	.read		= seq_read,
76 	.llseek		= seq_lseek,
77 	.release	= seq_release_net,
78 };
79 
80 struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
81 		struct proc_dir_entry *parent, const struct seq_operations *ops,
82 		unsigned int state_size, void *data)
83 {
84 	struct proc_dir_entry *p;
85 
86 	p = proc_create_reg(name, mode, &parent, data);
87 	if (!p)
88 		return NULL;
89 	p->proc_fops = &proc_net_seq_fops;
90 	p->seq_ops = ops;
91 	p->state_size = state_size;
92 	return proc_register(parent, p);
93 }
94 EXPORT_SYMBOL_GPL(proc_create_net_data);
95 
96 static int single_open_net(struct inode *inode, struct file *file)
97 {
98 	struct proc_dir_entry *de = PDE(inode);
99 	struct net *net;
100 	int err;
101 
102 	net = get_proc_net(inode);
103 	if (!net)
104 		return -ENXIO;
105 
106 	err = single_open(file, de->single_show, net);
107 	if (err)
108 		put_net(net);
109 	return err;
110 }
111 
112 static int single_release_net(struct inode *ino, struct file *f)
113 {
114 	struct seq_file *seq = f->private_data;
115 	put_net(seq->private);
116 	return single_release(ino, f);
117 }
118 
119 static const struct file_operations proc_net_single_fops = {
120 	.open		= single_open_net,
121 	.read		= seq_read,
122 	.llseek		= seq_lseek,
123 	.release	= single_release_net,
124 };
125 
126 struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
127 		struct proc_dir_entry *parent,
128 		int (*show)(struct seq_file *, void *), void *data)
129 {
130 	struct proc_dir_entry *p;
131 
132 	p = proc_create_reg(name, mode, &parent, data);
133 	if (!p)
134 		return NULL;
135 	p->proc_fops = &proc_net_single_fops;
136 	p->single_show = show;
137 	return proc_register(parent, p);
138 }
139 EXPORT_SYMBOL_GPL(proc_create_net_single);
140 
141 static struct net *get_proc_task_net(struct inode *dir)
142 {
143 	struct task_struct *task;
144 	struct nsproxy *ns;
145 	struct net *net = NULL;
146 
147 	rcu_read_lock();
148 	task = pid_task(proc_pid(dir), PIDTYPE_PID);
149 	if (task != NULL) {
150 		task_lock(task);
151 		ns = task->nsproxy;
152 		if (ns != NULL)
153 			net = get_net(ns->net_ns);
154 		task_unlock(task);
155 	}
156 	rcu_read_unlock();
157 
158 	return net;
159 }
160 
161 static struct dentry *proc_tgid_net_lookup(struct inode *dir,
162 		struct dentry *dentry, unsigned int flags)
163 {
164 	struct dentry *de;
165 	struct net *net;
166 
167 	de = ERR_PTR(-ENOENT);
168 	net = get_proc_task_net(dir);
169 	if (net != NULL) {
170 		de = proc_lookup_de(dir, dentry, net->proc_net);
171 		put_net(net);
172 	}
173 	return de;
174 }
175 
176 static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat,
177 				 u32 request_mask, unsigned int query_flags)
178 {
179 	struct inode *inode = d_inode(path->dentry);
180 	struct net *net;
181 
182 	net = get_proc_task_net(inode);
183 
184 	generic_fillattr(inode, stat);
185 
186 	if (net != NULL) {
187 		stat->nlink = net->proc_net->nlink;
188 		put_net(net);
189 	}
190 
191 	return 0;
192 }
193 
194 const struct inode_operations proc_net_inode_operations = {
195 	.lookup		= proc_tgid_net_lookup,
196 	.getattr	= proc_tgid_net_getattr,
197 };
198 
199 static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)
200 {
201 	int ret;
202 	struct net *net;
203 
204 	ret = -EINVAL;
205 	net = get_proc_task_net(file_inode(file));
206 	if (net != NULL) {
207 		ret = proc_readdir_de(file, ctx, net->proc_net);
208 		put_net(net);
209 	}
210 	return ret;
211 }
212 
213 const struct file_operations proc_net_operations = {
214 	.llseek		= generic_file_llseek,
215 	.read		= generic_read_dir,
216 	.iterate_shared	= proc_tgid_net_readdir,
217 };
218 
219 static __net_init int proc_net_ns_init(struct net *net)
220 {
221 	struct proc_dir_entry *netd, *net_statd;
222 	kuid_t uid;
223 	kgid_t gid;
224 	int err;
225 
226 	err = -ENOMEM;
227 	netd = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
228 	if (!netd)
229 		goto out;
230 
231 	netd->subdir = RB_ROOT;
232 	netd->data = net;
233 	netd->nlink = 2;
234 	netd->namelen = 3;
235 	netd->parent = &proc_root;
236 	netd->name = netd->inline_name;
237 	memcpy(netd->name, "net", 4);
238 
239 	uid = make_kuid(net->user_ns, 0);
240 	if (!uid_valid(uid))
241 		uid = netd->uid;
242 
243 	gid = make_kgid(net->user_ns, 0);
244 	if (!gid_valid(gid))
245 		gid = netd->gid;
246 
247 	proc_set_user(netd, uid, gid);
248 
249 	err = -EEXIST;
250 	net_statd = proc_net_mkdir(net, "stat", netd);
251 	if (!net_statd)
252 		goto free_net;
253 
254 	net->proc_net = netd;
255 	net->proc_net_stat = net_statd;
256 	return 0;
257 
258 free_net:
259 	pde_free(netd);
260 out:
261 	return err;
262 }
263 
264 static __net_exit void proc_net_ns_exit(struct net *net)
265 {
266 	remove_proc_entry("stat", net->proc_net);
267 	pde_free(net->proc_net);
268 }
269 
270 static struct pernet_operations __net_initdata proc_net_ns_ops = {
271 	.init = proc_net_ns_init,
272 	.exit = proc_net_ns_exit,
273 };
274 
275 int __init proc_net_init(void)
276 {
277 	proc_symlink("net", NULL, "self/net");
278 
279 	return register_pernet_subsys(&proc_net_ns_ops);
280 }
281