xref: /openbmc/linux/kernel/bpf/inode.c (revision 25fc94b2f02d832fa8e29419699dcc20b0b05c6a)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b2197755SDaniel Borkmann /*
3b2197755SDaniel Borkmann  * Minimal file system backend for holding eBPF maps and programs,
4b2197755SDaniel Borkmann  * used by bpf(2) object pinning.
5b2197755SDaniel Borkmann  *
6b2197755SDaniel Borkmann  * Authors:
7b2197755SDaniel Borkmann  *
8b2197755SDaniel Borkmann  *	Daniel Borkmann <daniel@iogearbox.net>
9b2197755SDaniel Borkmann  */
10b2197755SDaniel Borkmann 
11a536a6e1SPaul Gortmaker #include <linux/init.h>
12b2197755SDaniel Borkmann #include <linux/magic.h>
13b2197755SDaniel Borkmann #include <linux/major.h>
14b2197755SDaniel Borkmann #include <linux/mount.h>
15b2197755SDaniel Borkmann #include <linux/namei.h>
16b2197755SDaniel Borkmann #include <linux/fs.h>
17d2935de7SDavid Howells #include <linux/fs_context.h>
18d2935de7SDavid Howells #include <linux/fs_parser.h>
19b2197755SDaniel Borkmann #include <linux/kdev_t.h>
20b2197755SDaniel Borkmann #include <linux/filter.h>
21b2197755SDaniel Borkmann #include <linux/bpf.h>
22a67edbf4SDaniel Borkmann #include <linux/bpf_trace.h>
23d71fa5c9SAlexei Starovoitov #include "preload/bpf_preload.h"
24b2197755SDaniel Borkmann 
25b2197755SDaniel Borkmann enum bpf_type {
26b2197755SDaniel Borkmann 	BPF_TYPE_UNSPEC	= 0,
27b2197755SDaniel Borkmann 	BPF_TYPE_PROG,
28b2197755SDaniel Borkmann 	BPF_TYPE_MAP,
2970ed506cSAndrii Nakryiko 	BPF_TYPE_LINK,
30b2197755SDaniel Borkmann };
31b2197755SDaniel Borkmann 
32b2197755SDaniel Borkmann static void *bpf_any_get(void *raw, enum bpf_type type)
33b2197755SDaniel Borkmann {
34b2197755SDaniel Borkmann 	switch (type) {
35b2197755SDaniel Borkmann 	case BPF_TYPE_PROG:
3685192dbfSAndrii Nakryiko 		bpf_prog_inc(raw);
37b2197755SDaniel Borkmann 		break;
38b2197755SDaniel Borkmann 	case BPF_TYPE_MAP:
391e0bd5a0SAndrii Nakryiko 		bpf_map_inc_with_uref(raw);
40b2197755SDaniel Borkmann 		break;
4170ed506cSAndrii Nakryiko 	case BPF_TYPE_LINK:
4270ed506cSAndrii Nakryiko 		bpf_link_inc(raw);
4370ed506cSAndrii Nakryiko 		break;
44b2197755SDaniel Borkmann 	default:
45b2197755SDaniel Borkmann 		WARN_ON_ONCE(1);
46b2197755SDaniel Borkmann 		break;
47b2197755SDaniel Borkmann 	}
48b2197755SDaniel Borkmann 
49b2197755SDaniel Borkmann 	return raw;
50b2197755SDaniel Borkmann }
51b2197755SDaniel Borkmann 
52b2197755SDaniel Borkmann static void bpf_any_put(void *raw, enum bpf_type type)
53b2197755SDaniel Borkmann {
54b2197755SDaniel Borkmann 	switch (type) {
55b2197755SDaniel Borkmann 	case BPF_TYPE_PROG:
56b2197755SDaniel Borkmann 		bpf_prog_put(raw);
57b2197755SDaniel Borkmann 		break;
58b2197755SDaniel Borkmann 	case BPF_TYPE_MAP:
59c9da161cSDaniel Borkmann 		bpf_map_put_with_uref(raw);
60b2197755SDaniel Borkmann 		break;
6170ed506cSAndrii Nakryiko 	case BPF_TYPE_LINK:
6270ed506cSAndrii Nakryiko 		bpf_link_put(raw);
6370ed506cSAndrii Nakryiko 		break;
64b2197755SDaniel Borkmann 	default:
65b2197755SDaniel Borkmann 		WARN_ON_ONCE(1);
66b2197755SDaniel Borkmann 		break;
67b2197755SDaniel Borkmann 	}
68b2197755SDaniel Borkmann }
69b2197755SDaniel Borkmann 
70b2197755SDaniel Borkmann static void *bpf_fd_probe_obj(u32 ufd, enum bpf_type *type)
71b2197755SDaniel Borkmann {
72b2197755SDaniel Borkmann 	void *raw;
73b2197755SDaniel Borkmann 
74c9da161cSDaniel Borkmann 	raw = bpf_map_get_with_uref(ufd);
7570ed506cSAndrii Nakryiko 	if (!IS_ERR(raw)) {
7670ed506cSAndrii Nakryiko 		*type = BPF_TYPE_MAP;
7770ed506cSAndrii Nakryiko 		return raw;
78b2197755SDaniel Borkmann 	}
79b2197755SDaniel Borkmann 
8070ed506cSAndrii Nakryiko 	raw = bpf_prog_get(ufd);
8170ed506cSAndrii Nakryiko 	if (!IS_ERR(raw)) {
8270ed506cSAndrii Nakryiko 		*type = BPF_TYPE_PROG;
83b2197755SDaniel Borkmann 		return raw;
84b2197755SDaniel Borkmann 	}
85b2197755SDaniel Borkmann 
8670ed506cSAndrii Nakryiko 	raw = bpf_link_get_from_fd(ufd);
8770ed506cSAndrii Nakryiko 	if (!IS_ERR(raw)) {
8870ed506cSAndrii Nakryiko 		*type = BPF_TYPE_LINK;
8970ed506cSAndrii Nakryiko 		return raw;
9070ed506cSAndrii Nakryiko 	}
9170ed506cSAndrii Nakryiko 
9270ed506cSAndrii Nakryiko 	return ERR_PTR(-EINVAL);
9370ed506cSAndrii Nakryiko }
9470ed506cSAndrii Nakryiko 
95b2197755SDaniel Borkmann static const struct inode_operations bpf_dir_iops;
96b2197755SDaniel Borkmann 
97b2197755SDaniel Borkmann static const struct inode_operations bpf_prog_iops = { };
98b2197755SDaniel Borkmann static const struct inode_operations bpf_map_iops  = { };
9970ed506cSAndrii Nakryiko static const struct inode_operations bpf_link_iops  = { };
100b2197755SDaniel Borkmann 
101b2197755SDaniel Borkmann static struct inode *bpf_get_inode(struct super_block *sb,
102b2197755SDaniel Borkmann 				   const struct inode *dir,
103b2197755SDaniel Borkmann 				   umode_t mode)
104b2197755SDaniel Borkmann {
105b2197755SDaniel Borkmann 	struct inode *inode;
106b2197755SDaniel Borkmann 
107b2197755SDaniel Borkmann 	switch (mode & S_IFMT) {
108b2197755SDaniel Borkmann 	case S_IFDIR:
109b2197755SDaniel Borkmann 	case S_IFREG:
1100f98621bSDaniel Borkmann 	case S_IFLNK:
111b2197755SDaniel Borkmann 		break;
112b2197755SDaniel Borkmann 	default:
113b2197755SDaniel Borkmann 		return ERR_PTR(-EINVAL);
114b2197755SDaniel Borkmann 	}
115b2197755SDaniel Borkmann 
116b2197755SDaniel Borkmann 	inode = new_inode(sb);
117b2197755SDaniel Borkmann 	if (!inode)
118b2197755SDaniel Borkmann 		return ERR_PTR(-ENOSPC);
119b2197755SDaniel Borkmann 
120b2197755SDaniel Borkmann 	inode->i_ino = get_next_ino();
121078cd827SDeepa Dinamani 	inode->i_atime = current_time(inode);
122b2197755SDaniel Borkmann 	inode->i_mtime = inode->i_atime;
123b2197755SDaniel Borkmann 	inode->i_ctime = inode->i_atime;
124b2197755SDaniel Borkmann 
12521cb47beSChristian Brauner 	inode_init_owner(&init_user_ns, inode, dir, mode);
126b2197755SDaniel Borkmann 
127b2197755SDaniel Borkmann 	return inode;
128b2197755SDaniel Borkmann }
129b2197755SDaniel Borkmann 
130b2197755SDaniel Borkmann static int bpf_inode_type(const struct inode *inode, enum bpf_type *type)
131b2197755SDaniel Borkmann {
132b2197755SDaniel Borkmann 	*type = BPF_TYPE_UNSPEC;
133b2197755SDaniel Borkmann 	if (inode->i_op == &bpf_prog_iops)
134b2197755SDaniel Borkmann 		*type = BPF_TYPE_PROG;
135b2197755SDaniel Borkmann 	else if (inode->i_op == &bpf_map_iops)
136b2197755SDaniel Borkmann 		*type = BPF_TYPE_MAP;
13770ed506cSAndrii Nakryiko 	else if (inode->i_op == &bpf_link_iops)
13870ed506cSAndrii Nakryiko 		*type = BPF_TYPE_LINK;
139b2197755SDaniel Borkmann 	else
140b2197755SDaniel Borkmann 		return -EACCES;
141b2197755SDaniel Borkmann 
142b2197755SDaniel Borkmann 	return 0;
143b2197755SDaniel Borkmann }
144b2197755SDaniel Borkmann 
1450f98621bSDaniel Borkmann static void bpf_dentry_finalize(struct dentry *dentry, struct inode *inode,
1460f98621bSDaniel Borkmann 				struct inode *dir)
1470f98621bSDaniel Borkmann {
1480f98621bSDaniel Borkmann 	d_instantiate(dentry, inode);
1490f98621bSDaniel Borkmann 	dget(dentry);
1500f98621bSDaniel Borkmann 
1510f98621bSDaniel Borkmann 	dir->i_mtime = current_time(dir);
1520f98621bSDaniel Borkmann 	dir->i_ctime = dir->i_mtime;
1530f98621bSDaniel Borkmann }
1540f98621bSDaniel Borkmann 
155549c7297SChristian Brauner static int bpf_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
156549c7297SChristian Brauner 		     struct dentry *dentry, umode_t mode)
157b2197755SDaniel Borkmann {
158b2197755SDaniel Borkmann 	struct inode *inode;
159b2197755SDaniel Borkmann 
160b2197755SDaniel Borkmann 	inode = bpf_get_inode(dir->i_sb, dir, mode | S_IFDIR);
161b2197755SDaniel Borkmann 	if (IS_ERR(inode))
162b2197755SDaniel Borkmann 		return PTR_ERR(inode);
163b2197755SDaniel Borkmann 
164b2197755SDaniel Borkmann 	inode->i_op = &bpf_dir_iops;
165b2197755SDaniel Borkmann 	inode->i_fop = &simple_dir_operations;
166b2197755SDaniel Borkmann 
167b2197755SDaniel Borkmann 	inc_nlink(inode);
168b2197755SDaniel Borkmann 	inc_nlink(dir);
169b2197755SDaniel Borkmann 
1700f98621bSDaniel Borkmann 	bpf_dentry_finalize(dentry, inode, dir);
171b2197755SDaniel Borkmann 	return 0;
172b2197755SDaniel Borkmann }
173b2197755SDaniel Borkmann 
174a26ca7c9SMartin KaFai Lau struct map_iter {
175a26ca7c9SMartin KaFai Lau 	void *key;
176a26ca7c9SMartin KaFai Lau 	bool done;
177a26ca7c9SMartin KaFai Lau };
178a26ca7c9SMartin KaFai Lau 
179a26ca7c9SMartin KaFai Lau static struct map_iter *map_iter(struct seq_file *m)
180a26ca7c9SMartin KaFai Lau {
181a26ca7c9SMartin KaFai Lau 	return m->private;
182a26ca7c9SMartin KaFai Lau }
183a26ca7c9SMartin KaFai Lau 
184a26ca7c9SMartin KaFai Lau static struct bpf_map *seq_file_to_map(struct seq_file *m)
185a26ca7c9SMartin KaFai Lau {
186a26ca7c9SMartin KaFai Lau 	return file_inode(m->file)->i_private;
187a26ca7c9SMartin KaFai Lau }
188a26ca7c9SMartin KaFai Lau 
189a26ca7c9SMartin KaFai Lau static void map_iter_free(struct map_iter *iter)
190a26ca7c9SMartin KaFai Lau {
191a26ca7c9SMartin KaFai Lau 	if (iter) {
192a26ca7c9SMartin KaFai Lau 		kfree(iter->key);
193a26ca7c9SMartin KaFai Lau 		kfree(iter);
194a26ca7c9SMartin KaFai Lau 	}
195a26ca7c9SMartin KaFai Lau }
196a26ca7c9SMartin KaFai Lau 
197a26ca7c9SMartin KaFai Lau static struct map_iter *map_iter_alloc(struct bpf_map *map)
198a26ca7c9SMartin KaFai Lau {
199a26ca7c9SMartin KaFai Lau 	struct map_iter *iter;
200a26ca7c9SMartin KaFai Lau 
201a26ca7c9SMartin KaFai Lau 	iter = kzalloc(sizeof(*iter), GFP_KERNEL | __GFP_NOWARN);
202a26ca7c9SMartin KaFai Lau 	if (!iter)
203a26ca7c9SMartin KaFai Lau 		goto error;
204a26ca7c9SMartin KaFai Lau 
205a26ca7c9SMartin KaFai Lau 	iter->key = kzalloc(map->key_size, GFP_KERNEL | __GFP_NOWARN);
206a26ca7c9SMartin KaFai Lau 	if (!iter->key)
207a26ca7c9SMartin KaFai Lau 		goto error;
208a26ca7c9SMartin KaFai Lau 
209a26ca7c9SMartin KaFai Lau 	return iter;
210a26ca7c9SMartin KaFai Lau 
211a26ca7c9SMartin KaFai Lau error:
212a26ca7c9SMartin KaFai Lau 	map_iter_free(iter);
213a26ca7c9SMartin KaFai Lau 	return NULL;
214a26ca7c9SMartin KaFai Lau }
215a26ca7c9SMartin KaFai Lau 
216a26ca7c9SMartin KaFai Lau static void *map_seq_next(struct seq_file *m, void *v, loff_t *pos)
217a26ca7c9SMartin KaFai Lau {
218a26ca7c9SMartin KaFai Lau 	struct bpf_map *map = seq_file_to_map(m);
219a26ca7c9SMartin KaFai Lau 	void *key = map_iter(m)->key;
220dc1508a5SYonghong Song 	void *prev_key;
221a26ca7c9SMartin KaFai Lau 
22290435a78SVasily Averin 	(*pos)++;
223a26ca7c9SMartin KaFai Lau 	if (map_iter(m)->done)
224a26ca7c9SMartin KaFai Lau 		return NULL;
225a26ca7c9SMartin KaFai Lau 
226a26ca7c9SMartin KaFai Lau 	if (unlikely(v == SEQ_START_TOKEN))
227dc1508a5SYonghong Song 		prev_key = NULL;
228dc1508a5SYonghong Song 	else
229dc1508a5SYonghong Song 		prev_key = key;
230a26ca7c9SMartin KaFai Lau 
231ce880cb8SYonghong Song 	rcu_read_lock();
232dc1508a5SYonghong Song 	if (map->ops->map_get_next_key(map, prev_key, key)) {
233a26ca7c9SMartin KaFai Lau 		map_iter(m)->done = true;
234ce880cb8SYonghong Song 		key = NULL;
235a26ca7c9SMartin KaFai Lau 	}
236ce880cb8SYonghong Song 	rcu_read_unlock();
237a26ca7c9SMartin KaFai Lau 	return key;
238a26ca7c9SMartin KaFai Lau }
239a26ca7c9SMartin KaFai Lau 
240a26ca7c9SMartin KaFai Lau static void *map_seq_start(struct seq_file *m, loff_t *pos)
241a26ca7c9SMartin KaFai Lau {
242a26ca7c9SMartin KaFai Lau 	if (map_iter(m)->done)
243a26ca7c9SMartin KaFai Lau 		return NULL;
244a26ca7c9SMartin KaFai Lau 
245a26ca7c9SMartin KaFai Lau 	return *pos ? map_iter(m)->key : SEQ_START_TOKEN;
246a26ca7c9SMartin KaFai Lau }
247a26ca7c9SMartin KaFai Lau 
248a26ca7c9SMartin KaFai Lau static void map_seq_stop(struct seq_file *m, void *v)
249a26ca7c9SMartin KaFai Lau {
250a26ca7c9SMartin KaFai Lau }
251a26ca7c9SMartin KaFai Lau 
252a26ca7c9SMartin KaFai Lau static int map_seq_show(struct seq_file *m, void *v)
253a26ca7c9SMartin KaFai Lau {
254a26ca7c9SMartin KaFai Lau 	struct bpf_map *map = seq_file_to_map(m);
255a26ca7c9SMartin KaFai Lau 	void *key = map_iter(m)->key;
256a26ca7c9SMartin KaFai Lau 
257a26ca7c9SMartin KaFai Lau 	if (unlikely(v == SEQ_START_TOKEN)) {
258a26ca7c9SMartin KaFai Lau 		seq_puts(m, "# WARNING!! The output is for debug purpose only\n");
259a26ca7c9SMartin KaFai Lau 		seq_puts(m, "# WARNING!! The output format will change\n");
260a26ca7c9SMartin KaFai Lau 	} else {
261a26ca7c9SMartin KaFai Lau 		map->ops->map_seq_show_elem(map, key, m);
262a26ca7c9SMartin KaFai Lau 	}
263a26ca7c9SMartin KaFai Lau 
264a26ca7c9SMartin KaFai Lau 	return 0;
265a26ca7c9SMartin KaFai Lau }
266a26ca7c9SMartin KaFai Lau 
267a26ca7c9SMartin KaFai Lau static const struct seq_operations bpffs_map_seq_ops = {
268a26ca7c9SMartin KaFai Lau 	.start	= map_seq_start,
269a26ca7c9SMartin KaFai Lau 	.next	= map_seq_next,
270a26ca7c9SMartin KaFai Lau 	.show	= map_seq_show,
271a26ca7c9SMartin KaFai Lau 	.stop	= map_seq_stop,
272a26ca7c9SMartin KaFai Lau };
273a26ca7c9SMartin KaFai Lau 
274a26ca7c9SMartin KaFai Lau static int bpffs_map_open(struct inode *inode, struct file *file)
275a26ca7c9SMartin KaFai Lau {
276a26ca7c9SMartin KaFai Lau 	struct bpf_map *map = inode->i_private;
277a26ca7c9SMartin KaFai Lau 	struct map_iter *iter;
278a26ca7c9SMartin KaFai Lau 	struct seq_file *m;
279a26ca7c9SMartin KaFai Lau 	int err;
280a26ca7c9SMartin KaFai Lau 
281a26ca7c9SMartin KaFai Lau 	iter = map_iter_alloc(map);
282a26ca7c9SMartin KaFai Lau 	if (!iter)
283a26ca7c9SMartin KaFai Lau 		return -ENOMEM;
284a26ca7c9SMartin KaFai Lau 
285a26ca7c9SMartin KaFai Lau 	err = seq_open(file, &bpffs_map_seq_ops);
286a26ca7c9SMartin KaFai Lau 	if (err) {
287a26ca7c9SMartin KaFai Lau 		map_iter_free(iter);
288a26ca7c9SMartin KaFai Lau 		return err;
289a26ca7c9SMartin KaFai Lau 	}
290a26ca7c9SMartin KaFai Lau 
291a26ca7c9SMartin KaFai Lau 	m = file->private_data;
292a26ca7c9SMartin KaFai Lau 	m->private = iter;
293a26ca7c9SMartin KaFai Lau 
294a26ca7c9SMartin KaFai Lau 	return 0;
295a26ca7c9SMartin KaFai Lau }
296a26ca7c9SMartin KaFai Lau 
297a26ca7c9SMartin KaFai Lau static int bpffs_map_release(struct inode *inode, struct file *file)
298a26ca7c9SMartin KaFai Lau {
299a26ca7c9SMartin KaFai Lau 	struct seq_file *m = file->private_data;
300a26ca7c9SMartin KaFai Lau 
301a26ca7c9SMartin KaFai Lau 	map_iter_free(map_iter(m));
302a26ca7c9SMartin KaFai Lau 
303a26ca7c9SMartin KaFai Lau 	return seq_release(inode, file);
304a26ca7c9SMartin KaFai Lau }
305a26ca7c9SMartin KaFai Lau 
306a26ca7c9SMartin KaFai Lau /* bpffs_map_fops should only implement the basic
307a26ca7c9SMartin KaFai Lau  * read operation for a BPF map.  The purpose is to
308a26ca7c9SMartin KaFai Lau  * provide a simple user intuitive way to do
309a26ca7c9SMartin KaFai Lau  * "cat bpffs/pathto/a-pinned-map".
310a26ca7c9SMartin KaFai Lau  *
311a26ca7c9SMartin KaFai Lau  * Other operations (e.g. write, lookup...) should be realized by
312a26ca7c9SMartin KaFai Lau  * the userspace tools (e.g. bpftool) through the
313a26ca7c9SMartin KaFai Lau  * BPF_OBJ_GET_INFO_BY_FD and the map's lookup/update
314a26ca7c9SMartin KaFai Lau  * interface.
315a26ca7c9SMartin KaFai Lau  */
316a26ca7c9SMartin KaFai Lau static const struct file_operations bpffs_map_fops = {
317a26ca7c9SMartin KaFai Lau 	.open		= bpffs_map_open,
318a26ca7c9SMartin KaFai Lau 	.read		= seq_read,
319a26ca7c9SMartin KaFai Lau 	.release	= bpffs_map_release,
320a26ca7c9SMartin KaFai Lau };
321a26ca7c9SMartin KaFai Lau 
322b1655857SDaniel Borkmann static int bpffs_obj_open(struct inode *inode, struct file *file)
323b1655857SDaniel Borkmann {
324b1655857SDaniel Borkmann 	return -EIO;
325b1655857SDaniel Borkmann }
326b1655857SDaniel Borkmann 
327b1655857SDaniel Borkmann static const struct file_operations bpffs_obj_fops = {
328b1655857SDaniel Borkmann 	.open		= bpffs_obj_open,
329b1655857SDaniel Borkmann };
330b1655857SDaniel Borkmann 
331a4a0683fSAl Viro static int bpf_mkobj_ops(struct dentry *dentry, umode_t mode, void *raw,
332a26ca7c9SMartin KaFai Lau 			 const struct inode_operations *iops,
333a26ca7c9SMartin KaFai Lau 			 const struct file_operations *fops)
334b2197755SDaniel Borkmann {
335a4a0683fSAl Viro 	struct inode *dir = dentry->d_parent->d_inode;
336a4a0683fSAl Viro 	struct inode *inode = bpf_get_inode(dir->i_sb, dir, mode);
337b2197755SDaniel Borkmann 	if (IS_ERR(inode))
338b2197755SDaniel Borkmann 		return PTR_ERR(inode);
339b2197755SDaniel Borkmann 
340b2197755SDaniel Borkmann 	inode->i_op = iops;
341a26ca7c9SMartin KaFai Lau 	inode->i_fop = fops;
342a4a0683fSAl Viro 	inode->i_private = raw;
343b2197755SDaniel Borkmann 
3440f98621bSDaniel Borkmann 	bpf_dentry_finalize(dentry, inode, dir);
345b2197755SDaniel Borkmann 	return 0;
346b2197755SDaniel Borkmann }
347b2197755SDaniel Borkmann 
348a4a0683fSAl Viro static int bpf_mkprog(struct dentry *dentry, umode_t mode, void *arg)
349b2197755SDaniel Borkmann {
350b1655857SDaniel Borkmann 	return bpf_mkobj_ops(dentry, mode, arg, &bpf_prog_iops,
351b1655857SDaniel Borkmann 			     &bpffs_obj_fops);
352b2197755SDaniel Borkmann }
353a4a0683fSAl Viro 
354a4a0683fSAl Viro static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
355a4a0683fSAl Viro {
356a26ca7c9SMartin KaFai Lau 	struct bpf_map *map = arg;
357a26ca7c9SMartin KaFai Lau 
358a26ca7c9SMartin KaFai Lau 	return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
359e8d2bec0SDaniel Borkmann 			     bpf_map_support_seq_show(map) ?
360e8d2bec0SDaniel Borkmann 			     &bpffs_map_fops : &bpffs_obj_fops);
361b2197755SDaniel Borkmann }
362b2197755SDaniel Borkmann 
36370ed506cSAndrii Nakryiko static int bpf_mklink(struct dentry *dentry, umode_t mode, void *arg)
36470ed506cSAndrii Nakryiko {
365367ec3e4SYonghong Song 	struct bpf_link *link = arg;
366367ec3e4SYonghong Song 
36770ed506cSAndrii Nakryiko 	return bpf_mkobj_ops(dentry, mode, arg, &bpf_link_iops,
368367ec3e4SYonghong Song 			     bpf_link_is_iter(link) ?
369367ec3e4SYonghong Song 			     &bpf_iter_fops : &bpffs_obj_fops);
37070ed506cSAndrii Nakryiko }
37170ed506cSAndrii Nakryiko 
3720c93b7d8SAl Viro static struct dentry *
3730c93b7d8SAl Viro bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags)
374bb35a6efSDaniel Borkmann {
3756d8cb045SQuentin Monnet 	/* Dots in names (e.g. "/sys/fs/bpf/foo.bar") are reserved for future
376d71fa5c9SAlexei Starovoitov 	 * extensions. That allows popoulate_bpffs() create special files.
3776d8cb045SQuentin Monnet 	 */
378d71fa5c9SAlexei Starovoitov 	if ((dir->i_mode & S_IALLUGO) &&
379d71fa5c9SAlexei Starovoitov 	    strchr(dentry->d_name.name, '.'))
3800c93b7d8SAl Viro 		return ERR_PTR(-EPERM);
3810f98621bSDaniel Borkmann 
3820c93b7d8SAl Viro 	return simple_lookup(dir, dentry, flags);
383bb35a6efSDaniel Borkmann }
384bb35a6efSDaniel Borkmann 
385549c7297SChristian Brauner static int bpf_symlink(struct user_namespace *mnt_userns, struct inode *dir,
386549c7297SChristian Brauner 		       struct dentry *dentry, const char *target)
3870f98621bSDaniel Borkmann {
3880f98621bSDaniel Borkmann 	char *link = kstrdup(target, GFP_USER | __GFP_NOWARN);
3890f98621bSDaniel Borkmann 	struct inode *inode;
3900f98621bSDaniel Borkmann 
3910f98621bSDaniel Borkmann 	if (!link)
3920f98621bSDaniel Borkmann 		return -ENOMEM;
3930f98621bSDaniel Borkmann 
3940f98621bSDaniel Borkmann 	inode = bpf_get_inode(dir->i_sb, dir, S_IRWXUGO | S_IFLNK);
3950f98621bSDaniel Borkmann 	if (IS_ERR(inode)) {
3960f98621bSDaniel Borkmann 		kfree(link);
3970f98621bSDaniel Borkmann 		return PTR_ERR(inode);
3980f98621bSDaniel Borkmann 	}
3990f98621bSDaniel Borkmann 
4000f98621bSDaniel Borkmann 	inode->i_op = &simple_symlink_inode_operations;
4010f98621bSDaniel Borkmann 	inode->i_link = link;
4020f98621bSDaniel Borkmann 
4030f98621bSDaniel Borkmann 	bpf_dentry_finalize(dentry, inode, dir);
4040f98621bSDaniel Borkmann 	return 0;
4050f98621bSDaniel Borkmann }
4060f98621bSDaniel Borkmann 
407b2197755SDaniel Borkmann static const struct inode_operations bpf_dir_iops = {
4080c93b7d8SAl Viro 	.lookup		= bpf_lookup,
409b2197755SDaniel Borkmann 	.mkdir		= bpf_mkdir,
4100f98621bSDaniel Borkmann 	.symlink	= bpf_symlink,
411b2197755SDaniel Borkmann 	.rmdir		= simple_rmdir,
4120c93b7d8SAl Viro 	.rename		= simple_rename,
4130c93b7d8SAl Viro 	.link		= simple_link,
414b2197755SDaniel Borkmann 	.unlink		= simple_unlink,
415b2197755SDaniel Borkmann };
416b2197755SDaniel Borkmann 
417d71fa5c9SAlexei Starovoitov /* pin iterator link into bpffs */
418d71fa5c9SAlexei Starovoitov static int bpf_iter_link_pin_kernel(struct dentry *parent,
419d71fa5c9SAlexei Starovoitov 				    const char *name, struct bpf_link *link)
420d71fa5c9SAlexei Starovoitov {
421d71fa5c9SAlexei Starovoitov 	umode_t mode = S_IFREG | S_IRUSR;
422d71fa5c9SAlexei Starovoitov 	struct dentry *dentry;
423d71fa5c9SAlexei Starovoitov 	int ret;
424d71fa5c9SAlexei Starovoitov 
425d71fa5c9SAlexei Starovoitov 	inode_lock(parent->d_inode);
426d71fa5c9SAlexei Starovoitov 	dentry = lookup_one_len(name, parent, strlen(name));
427d71fa5c9SAlexei Starovoitov 	if (IS_ERR(dentry)) {
428d71fa5c9SAlexei Starovoitov 		inode_unlock(parent->d_inode);
429d71fa5c9SAlexei Starovoitov 		return PTR_ERR(dentry);
430d71fa5c9SAlexei Starovoitov 	}
431d71fa5c9SAlexei Starovoitov 	ret = bpf_mkobj_ops(dentry, mode, link, &bpf_link_iops,
432d71fa5c9SAlexei Starovoitov 			    &bpf_iter_fops);
433d71fa5c9SAlexei Starovoitov 	dput(dentry);
434d71fa5c9SAlexei Starovoitov 	inode_unlock(parent->d_inode);
435d71fa5c9SAlexei Starovoitov 	return ret;
436d71fa5c9SAlexei Starovoitov }
437d71fa5c9SAlexei Starovoitov 
438b87121ddSAl Viro static int bpf_obj_do_pin(const char __user *pathname, void *raw,
439b2197755SDaniel Borkmann 			  enum bpf_type type)
440b2197755SDaniel Borkmann {
441b2197755SDaniel Borkmann 	struct dentry *dentry;
442b2197755SDaniel Borkmann 	struct inode *dir;
443b2197755SDaniel Borkmann 	struct path path;
444b2197755SDaniel Borkmann 	umode_t mode;
445b2197755SDaniel Borkmann 	int ret;
446b2197755SDaniel Borkmann 
447b87121ddSAl Viro 	dentry = user_path_create(AT_FDCWD, pathname, &path, 0);
448b2197755SDaniel Borkmann 	if (IS_ERR(dentry))
449b2197755SDaniel Borkmann 		return PTR_ERR(dentry);
450b2197755SDaniel Borkmann 
451b2197755SDaniel Borkmann 	mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask());
452b2197755SDaniel Borkmann 
453a4a0683fSAl Viro 	ret = security_path_mknod(&path, dentry, mode, 0);
454b2197755SDaniel Borkmann 	if (ret)
455b2197755SDaniel Borkmann 		goto out;
456b2197755SDaniel Borkmann 
457b2197755SDaniel Borkmann 	dir = d_inode(path.dentry);
458b2197755SDaniel Borkmann 	if (dir->i_op != &bpf_dir_iops) {
459b2197755SDaniel Borkmann 		ret = -EPERM;
460b2197755SDaniel Borkmann 		goto out;
461b2197755SDaniel Borkmann 	}
462b2197755SDaniel Borkmann 
463a4a0683fSAl Viro 	switch (type) {
464a4a0683fSAl Viro 	case BPF_TYPE_PROG:
465a4a0683fSAl Viro 		ret = vfs_mkobj(dentry, mode, bpf_mkprog, raw);
466a4a0683fSAl Viro 		break;
467a4a0683fSAl Viro 	case BPF_TYPE_MAP:
468a4a0683fSAl Viro 		ret = vfs_mkobj(dentry, mode, bpf_mkmap, raw);
469a4a0683fSAl Viro 		break;
47070ed506cSAndrii Nakryiko 	case BPF_TYPE_LINK:
47170ed506cSAndrii Nakryiko 		ret = vfs_mkobj(dentry, mode, bpf_mklink, raw);
47270ed506cSAndrii Nakryiko 		break;
473a4a0683fSAl Viro 	default:
474a4a0683fSAl Viro 		ret = -EPERM;
475a4a0683fSAl Viro 	}
476b2197755SDaniel Borkmann out:
477b2197755SDaniel Borkmann 	done_path_create(&path, dentry);
478b2197755SDaniel Borkmann 	return ret;
479b2197755SDaniel Borkmann }
480b2197755SDaniel Borkmann 
481b2197755SDaniel Borkmann int bpf_obj_pin_user(u32 ufd, const char __user *pathname)
482b2197755SDaniel Borkmann {
483b2197755SDaniel Borkmann 	enum bpf_type type;
484b2197755SDaniel Borkmann 	void *raw;
485b2197755SDaniel Borkmann 	int ret;
486b2197755SDaniel Borkmann 
487b2197755SDaniel Borkmann 	raw = bpf_fd_probe_obj(ufd, &type);
488b87121ddSAl Viro 	if (IS_ERR(raw))
489b87121ddSAl Viro 		return PTR_ERR(raw);
490b2197755SDaniel Borkmann 
491b87121ddSAl Viro 	ret = bpf_obj_do_pin(pathname, raw, type);
492b2197755SDaniel Borkmann 	if (ret != 0)
493b2197755SDaniel Borkmann 		bpf_any_put(raw, type);
494b87121ddSAl Viro 
495b2197755SDaniel Borkmann 	return ret;
496b2197755SDaniel Borkmann }
497b2197755SDaniel Borkmann 
498b87121ddSAl Viro static void *bpf_obj_do_get(const char __user *pathname,
4996e71b04aSChenbo Feng 			    enum bpf_type *type, int flags)
500b2197755SDaniel Borkmann {
501b2197755SDaniel Borkmann 	struct inode *inode;
502b2197755SDaniel Borkmann 	struct path path;
503b2197755SDaniel Borkmann 	void *raw;
504b2197755SDaniel Borkmann 	int ret;
505b2197755SDaniel Borkmann 
506b87121ddSAl Viro 	ret = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
507b2197755SDaniel Borkmann 	if (ret)
508b2197755SDaniel Borkmann 		return ERR_PTR(ret);
509b2197755SDaniel Borkmann 
510b2197755SDaniel Borkmann 	inode = d_backing_inode(path.dentry);
51102f92b38SChristian Brauner 	ret = path_permission(&path, ACC_MODE(flags));
512b2197755SDaniel Borkmann 	if (ret)
513b2197755SDaniel Borkmann 		goto out;
514b2197755SDaniel Borkmann 
515b2197755SDaniel Borkmann 	ret = bpf_inode_type(inode, type);
516b2197755SDaniel Borkmann 	if (ret)
517b2197755SDaniel Borkmann 		goto out;
518b2197755SDaniel Borkmann 
519b2197755SDaniel Borkmann 	raw = bpf_any_get(inode->i_private, *type);
52092117d84SAlexei Starovoitov 	if (!IS_ERR(raw))
521b2197755SDaniel Borkmann 		touch_atime(&path);
522b2197755SDaniel Borkmann 
523b2197755SDaniel Borkmann 	path_put(&path);
524b2197755SDaniel Borkmann 	return raw;
525b2197755SDaniel Borkmann out:
526b2197755SDaniel Borkmann 	path_put(&path);
527b2197755SDaniel Borkmann 	return ERR_PTR(ret);
528b2197755SDaniel Borkmann }
529b2197755SDaniel Borkmann 
5306e71b04aSChenbo Feng int bpf_obj_get_user(const char __user *pathname, int flags)
531b2197755SDaniel Borkmann {
532b2197755SDaniel Borkmann 	enum bpf_type type = BPF_TYPE_UNSPEC;
5336e71b04aSChenbo Feng 	int f_flags;
534b2197755SDaniel Borkmann 	void *raw;
535b87121ddSAl Viro 	int ret;
536b2197755SDaniel Borkmann 
5376e71b04aSChenbo Feng 	f_flags = bpf_get_file_flag(flags);
5386e71b04aSChenbo Feng 	if (f_flags < 0)
5396e71b04aSChenbo Feng 		return f_flags;
5406e71b04aSChenbo Feng 
541b87121ddSAl Viro 	raw = bpf_obj_do_get(pathname, &type, f_flags);
542b87121ddSAl Viro 	if (IS_ERR(raw))
543b87121ddSAl Viro 		return PTR_ERR(raw);
544b2197755SDaniel Borkmann 
545b2197755SDaniel Borkmann 	if (type == BPF_TYPE_PROG)
546b2197755SDaniel Borkmann 		ret = bpf_prog_new_fd(raw);
547b2197755SDaniel Borkmann 	else if (type == BPF_TYPE_MAP)
5486e71b04aSChenbo Feng 		ret = bpf_map_new_fd(raw, f_flags);
54970ed506cSAndrii Nakryiko 	else if (type == BPF_TYPE_LINK)
550*25fc94b2SLorenz Bauer 		ret = (f_flags != O_RDWR) ? -EINVAL : bpf_link_new_fd(raw);
551b2197755SDaniel Borkmann 	else
552b87121ddSAl Viro 		return -ENOENT;
553b2197755SDaniel Borkmann 
5544d220ed0SAlexei Starovoitov 	if (ret < 0)
555b2197755SDaniel Borkmann 		bpf_any_put(raw, type);
556b2197755SDaniel Borkmann 	return ret;
557b2197755SDaniel Borkmann }
558040ee692SAl Viro 
559040ee692SAl Viro static struct bpf_prog *__get_prog_inode(struct inode *inode, enum bpf_prog_type type)
560040ee692SAl Viro {
561040ee692SAl Viro 	struct bpf_prog *prog;
56247291baaSChristian Brauner 	int ret = inode_permission(&init_user_ns, inode, MAY_READ);
563040ee692SAl Viro 	if (ret)
564040ee692SAl Viro 		return ERR_PTR(ret);
565040ee692SAl Viro 
566040ee692SAl Viro 	if (inode->i_op == &bpf_map_iops)
567040ee692SAl Viro 		return ERR_PTR(-EINVAL);
56870ed506cSAndrii Nakryiko 	if (inode->i_op == &bpf_link_iops)
56970ed506cSAndrii Nakryiko 		return ERR_PTR(-EINVAL);
570040ee692SAl Viro 	if (inode->i_op != &bpf_prog_iops)
571040ee692SAl Viro 		return ERR_PTR(-EACCES);
572040ee692SAl Viro 
573040ee692SAl Viro 	prog = inode->i_private;
574040ee692SAl Viro 
575040ee692SAl Viro 	ret = security_bpf_prog(prog);
576040ee692SAl Viro 	if (ret < 0)
577040ee692SAl Viro 		return ERR_PTR(ret);
578040ee692SAl Viro 
579040ee692SAl Viro 	if (!bpf_prog_get_ok(prog, &type, false))
580040ee692SAl Viro 		return ERR_PTR(-EINVAL);
581040ee692SAl Viro 
58285192dbfSAndrii Nakryiko 	bpf_prog_inc(prog);
58385192dbfSAndrii Nakryiko 	return prog;
584040ee692SAl Viro }
585040ee692SAl Viro 
586040ee692SAl Viro struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type)
587040ee692SAl Viro {
588040ee692SAl Viro 	struct bpf_prog *prog;
589040ee692SAl Viro 	struct path path;
590040ee692SAl Viro 	int ret = kern_path(name, LOOKUP_FOLLOW, &path);
591040ee692SAl Viro 	if (ret)
592040ee692SAl Viro 		return ERR_PTR(ret);
593040ee692SAl Viro 	prog = __get_prog_inode(d_backing_inode(path.dentry), type);
594040ee692SAl Viro 	if (!IS_ERR(prog))
595040ee692SAl Viro 		touch_atime(&path);
596040ee692SAl Viro 	path_put(&path);
597040ee692SAl Viro 	return prog;
598040ee692SAl Viro }
599040ee692SAl Viro EXPORT_SYMBOL(bpf_prog_get_type_path);
600b2197755SDaniel Borkmann 
6014cc7c186SDavid Howells /*
6024cc7c186SDavid Howells  * Display the mount options in /proc/mounts.
6034cc7c186SDavid Howells  */
6044cc7c186SDavid Howells static int bpf_show_options(struct seq_file *m, struct dentry *root)
6054cc7c186SDavid Howells {
6064cc7c186SDavid Howells 	umode_t mode = d_inode(root)->i_mode & S_IALLUGO & ~S_ISVTX;
6074cc7c186SDavid Howells 
6084cc7c186SDavid Howells 	if (mode != S_IRWXUGO)
6094cc7c186SDavid Howells 		seq_printf(m, ",mode=%o", mode);
6104cc7c186SDavid Howells 	return 0;
6114cc7c186SDavid Howells }
6124cc7c186SDavid Howells 
613524845ffSAl Viro static void bpf_free_inode(struct inode *inode)
6141da6c4d9SDaniel Borkmann {
6151da6c4d9SDaniel Borkmann 	enum bpf_type type;
6161da6c4d9SDaniel Borkmann 
6171da6c4d9SDaniel Borkmann 	if (S_ISLNK(inode->i_mode))
6181da6c4d9SDaniel Borkmann 		kfree(inode->i_link);
6191da6c4d9SDaniel Borkmann 	if (!bpf_inode_type(inode, &type))
6201da6c4d9SDaniel Borkmann 		bpf_any_put(inode->i_private, type);
6211da6c4d9SDaniel Borkmann 	free_inode_nonrcu(inode);
6221da6c4d9SDaniel Borkmann }
6231da6c4d9SDaniel Borkmann 
624b2197755SDaniel Borkmann static const struct super_operations bpf_super_ops = {
625b2197755SDaniel Borkmann 	.statfs		= simple_statfs,
626b2197755SDaniel Borkmann 	.drop_inode	= generic_delete_inode,
6274cc7c186SDavid Howells 	.show_options	= bpf_show_options,
628524845ffSAl Viro 	.free_inode	= bpf_free_inode,
629b2197755SDaniel Borkmann };
630b2197755SDaniel Borkmann 
631a3af5f80SDaniel Borkmann enum {
632a3af5f80SDaniel Borkmann 	OPT_MODE,
633a3af5f80SDaniel Borkmann };
634a3af5f80SDaniel Borkmann 
635d7167b14SAl Viro static const struct fs_parameter_spec bpf_fs_parameters[] = {
636d2935de7SDavid Howells 	fsparam_u32oct	("mode",			OPT_MODE),
637d2935de7SDavid Howells 	{}
638d2935de7SDavid Howells };
639d2935de7SDavid Howells 
640a3af5f80SDaniel Borkmann struct bpf_mount_opts {
641a3af5f80SDaniel Borkmann 	umode_t mode;
642a3af5f80SDaniel Borkmann };
643a3af5f80SDaniel Borkmann 
644d2935de7SDavid Howells static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param)
645a3af5f80SDaniel Borkmann {
646d2935de7SDavid Howells 	struct bpf_mount_opts *opts = fc->fs_private;
647d2935de7SDavid Howells 	struct fs_parse_result result;
648d2935de7SDavid Howells 	int opt;
649a3af5f80SDaniel Borkmann 
650d7167b14SAl Viro 	opt = fs_parse(fc, bpf_fs_parameters, param, &result);
651d2935de7SDavid Howells 	if (opt < 0)
652a3af5f80SDaniel Borkmann 		/* We might like to report bad mount options here, but
653a3af5f80SDaniel Borkmann 		 * traditionally we've ignored all mount options, so we'd
654a3af5f80SDaniel Borkmann 		 * better continue to ignore non-existing options for bpf.
655a3af5f80SDaniel Borkmann 		 */
656d2935de7SDavid Howells 		return opt == -ENOPARAM ? 0 : opt;
657d2935de7SDavid Howells 
658d2935de7SDavid Howells 	switch (opt) {
659d2935de7SDavid Howells 	case OPT_MODE:
660d2935de7SDavid Howells 		opts->mode = result.uint_32 & S_IALLUGO;
661d2935de7SDavid Howells 		break;
662a3af5f80SDaniel Borkmann 	}
663a3af5f80SDaniel Borkmann 
664a3af5f80SDaniel Borkmann 	return 0;
665a3af5f80SDaniel Borkmann }
666a3af5f80SDaniel Borkmann 
667d71fa5c9SAlexei Starovoitov struct bpf_preload_ops *bpf_preload_ops;
668d71fa5c9SAlexei Starovoitov EXPORT_SYMBOL_GPL(bpf_preload_ops);
669d71fa5c9SAlexei Starovoitov 
670d71fa5c9SAlexei Starovoitov static bool bpf_preload_mod_get(void)
671d71fa5c9SAlexei Starovoitov {
672d71fa5c9SAlexei Starovoitov 	/* If bpf_preload.ko wasn't loaded earlier then load it now.
673d71fa5c9SAlexei Starovoitov 	 * When bpf_preload is built into vmlinux the module's __init
674d71fa5c9SAlexei Starovoitov 	 * function will populate it.
675d71fa5c9SAlexei Starovoitov 	 */
676d71fa5c9SAlexei Starovoitov 	if (!bpf_preload_ops) {
677d71fa5c9SAlexei Starovoitov 		request_module("bpf_preload");
678d71fa5c9SAlexei Starovoitov 		if (!bpf_preload_ops)
679d71fa5c9SAlexei Starovoitov 			return false;
680d71fa5c9SAlexei Starovoitov 	}
681d71fa5c9SAlexei Starovoitov 	/* And grab the reference, so the module doesn't disappear while the
682d71fa5c9SAlexei Starovoitov 	 * kernel is interacting with the kernel module and its UMD.
683d71fa5c9SAlexei Starovoitov 	 */
684d71fa5c9SAlexei Starovoitov 	if (!try_module_get(bpf_preload_ops->owner)) {
685d71fa5c9SAlexei Starovoitov 		pr_err("bpf_preload module get failed.\n");
686d71fa5c9SAlexei Starovoitov 		return false;
687d71fa5c9SAlexei Starovoitov 	}
688d71fa5c9SAlexei Starovoitov 	return true;
689d71fa5c9SAlexei Starovoitov }
690d71fa5c9SAlexei Starovoitov 
691d71fa5c9SAlexei Starovoitov static void bpf_preload_mod_put(void)
692d71fa5c9SAlexei Starovoitov {
693d71fa5c9SAlexei Starovoitov 	if (bpf_preload_ops)
694d71fa5c9SAlexei Starovoitov 		/* now user can "rmmod bpf_preload" if necessary */
695d71fa5c9SAlexei Starovoitov 		module_put(bpf_preload_ops->owner);
696d71fa5c9SAlexei Starovoitov }
697d71fa5c9SAlexei Starovoitov 
698d71fa5c9SAlexei Starovoitov static DEFINE_MUTEX(bpf_preload_lock);
699d71fa5c9SAlexei Starovoitov 
700d71fa5c9SAlexei Starovoitov static int populate_bpffs(struct dentry *parent)
701d71fa5c9SAlexei Starovoitov {
702d71fa5c9SAlexei Starovoitov 	struct bpf_preload_info objs[BPF_PRELOAD_LINKS] = {};
703d71fa5c9SAlexei Starovoitov 	struct bpf_link *links[BPF_PRELOAD_LINKS] = {};
704d71fa5c9SAlexei Starovoitov 	int err = 0, i;
705d71fa5c9SAlexei Starovoitov 
706d71fa5c9SAlexei Starovoitov 	/* grab the mutex to make sure the kernel interactions with bpf_preload
707d71fa5c9SAlexei Starovoitov 	 * UMD are serialized
708d71fa5c9SAlexei Starovoitov 	 */
709d71fa5c9SAlexei Starovoitov 	mutex_lock(&bpf_preload_lock);
710d71fa5c9SAlexei Starovoitov 
711d71fa5c9SAlexei Starovoitov 	/* if bpf_preload.ko wasn't built into vmlinux then load it */
712d71fa5c9SAlexei Starovoitov 	if (!bpf_preload_mod_get())
713d71fa5c9SAlexei Starovoitov 		goto out;
714d71fa5c9SAlexei Starovoitov 
715d71fa5c9SAlexei Starovoitov 	if (!bpf_preload_ops->info.tgid) {
716d71fa5c9SAlexei Starovoitov 		/* preload() will start UMD that will load BPF iterator programs */
717d71fa5c9SAlexei Starovoitov 		err = bpf_preload_ops->preload(objs);
718d71fa5c9SAlexei Starovoitov 		if (err)
719d71fa5c9SAlexei Starovoitov 			goto out_put;
720d71fa5c9SAlexei Starovoitov 		for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
721d71fa5c9SAlexei Starovoitov 			links[i] = bpf_link_by_id(objs[i].link_id);
722d71fa5c9SAlexei Starovoitov 			if (IS_ERR(links[i])) {
723d71fa5c9SAlexei Starovoitov 				err = PTR_ERR(links[i]);
724d71fa5c9SAlexei Starovoitov 				goto out_put;
725d71fa5c9SAlexei Starovoitov 			}
726d71fa5c9SAlexei Starovoitov 		}
727d71fa5c9SAlexei Starovoitov 		for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
728d71fa5c9SAlexei Starovoitov 			err = bpf_iter_link_pin_kernel(parent,
729d71fa5c9SAlexei Starovoitov 						       objs[i].link_name, links[i]);
730d71fa5c9SAlexei Starovoitov 			if (err)
731d71fa5c9SAlexei Starovoitov 				goto out_put;
732d71fa5c9SAlexei Starovoitov 			/* do not unlink successfully pinned links even
733d71fa5c9SAlexei Starovoitov 			 * if later link fails to pin
734d71fa5c9SAlexei Starovoitov 			 */
735d71fa5c9SAlexei Starovoitov 			links[i] = NULL;
736d71fa5c9SAlexei Starovoitov 		}
737d71fa5c9SAlexei Starovoitov 		/* finish() will tell UMD process to exit */
738d71fa5c9SAlexei Starovoitov 		err = bpf_preload_ops->finish();
739d71fa5c9SAlexei Starovoitov 		if (err)
740d71fa5c9SAlexei Starovoitov 			goto out_put;
741d71fa5c9SAlexei Starovoitov 	}
742d71fa5c9SAlexei Starovoitov out_put:
743d71fa5c9SAlexei Starovoitov 	bpf_preload_mod_put();
744d71fa5c9SAlexei Starovoitov out:
745d71fa5c9SAlexei Starovoitov 	mutex_unlock(&bpf_preload_lock);
746d71fa5c9SAlexei Starovoitov 	for (i = 0; i < BPF_PRELOAD_LINKS && err; i++)
747d71fa5c9SAlexei Starovoitov 		if (!IS_ERR_OR_NULL(links[i]))
748d71fa5c9SAlexei Starovoitov 			bpf_link_put(links[i]);
749d71fa5c9SAlexei Starovoitov 	return err;
750d71fa5c9SAlexei Starovoitov }
751d71fa5c9SAlexei Starovoitov 
752d2935de7SDavid Howells static int bpf_fill_super(struct super_block *sb, struct fs_context *fc)
753b2197755SDaniel Borkmann {
754cda37124SEric Biggers 	static const struct tree_descr bpf_rfiles[] = { { "" } };
755d2935de7SDavid Howells 	struct bpf_mount_opts *opts = fc->fs_private;
756b2197755SDaniel Borkmann 	struct inode *inode;
757b2197755SDaniel Borkmann 	int ret;
758b2197755SDaniel Borkmann 
759b2197755SDaniel Borkmann 	ret = simple_fill_super(sb, BPF_FS_MAGIC, bpf_rfiles);
760b2197755SDaniel Borkmann 	if (ret)
761b2197755SDaniel Borkmann 		return ret;
762b2197755SDaniel Borkmann 
763b2197755SDaniel Borkmann 	sb->s_op = &bpf_super_ops;
764b2197755SDaniel Borkmann 
765b2197755SDaniel Borkmann 	inode = sb->s_root->d_inode;
766b2197755SDaniel Borkmann 	inode->i_op = &bpf_dir_iops;
767b2197755SDaniel Borkmann 	inode->i_mode &= ~S_IALLUGO;
768d71fa5c9SAlexei Starovoitov 	populate_bpffs(sb->s_root);
769d2935de7SDavid Howells 	inode->i_mode |= S_ISVTX | opts->mode;
770b2197755SDaniel Borkmann 	return 0;
771b2197755SDaniel Borkmann }
772b2197755SDaniel Borkmann 
773d2935de7SDavid Howells static int bpf_get_tree(struct fs_context *fc)
774b2197755SDaniel Borkmann {
775d2935de7SDavid Howells 	return get_tree_nodev(fc, bpf_fill_super);
776d2935de7SDavid Howells }
777d2935de7SDavid Howells 
778d2935de7SDavid Howells static void bpf_free_fc(struct fs_context *fc)
779d2935de7SDavid Howells {
780d2935de7SDavid Howells 	kfree(fc->fs_private);
781d2935de7SDavid Howells }
782d2935de7SDavid Howells 
783d2935de7SDavid Howells static const struct fs_context_operations bpf_context_ops = {
784d2935de7SDavid Howells 	.free		= bpf_free_fc,
785d2935de7SDavid Howells 	.parse_param	= bpf_parse_param,
786d2935de7SDavid Howells 	.get_tree	= bpf_get_tree,
787d2935de7SDavid Howells };
788d2935de7SDavid Howells 
789d2935de7SDavid Howells /*
790d2935de7SDavid Howells  * Set up the filesystem mount context.
791d2935de7SDavid Howells  */
792d2935de7SDavid Howells static int bpf_init_fs_context(struct fs_context *fc)
793d2935de7SDavid Howells {
794d2935de7SDavid Howells 	struct bpf_mount_opts *opts;
795d2935de7SDavid Howells 
796d2935de7SDavid Howells 	opts = kzalloc(sizeof(struct bpf_mount_opts), GFP_KERNEL);
797d2935de7SDavid Howells 	if (!opts)
798d2935de7SDavid Howells 		return -ENOMEM;
799d2935de7SDavid Howells 
800d2935de7SDavid Howells 	opts->mode = S_IRWXUGO;
801d2935de7SDavid Howells 
802d2935de7SDavid Howells 	fc->fs_private = opts;
803d2935de7SDavid Howells 	fc->ops = &bpf_context_ops;
804d2935de7SDavid Howells 	return 0;
805b2197755SDaniel Borkmann }
806b2197755SDaniel Borkmann 
807b2197755SDaniel Borkmann static struct file_system_type bpf_fs_type = {
808b2197755SDaniel Borkmann 	.owner		= THIS_MODULE,
809b2197755SDaniel Borkmann 	.name		= "bpf",
810d2935de7SDavid Howells 	.init_fs_context = bpf_init_fs_context,
811d7167b14SAl Viro 	.parameters	= bpf_fs_parameters,
812b2197755SDaniel Borkmann 	.kill_sb	= kill_litter_super,
813b2197755SDaniel Borkmann };
814b2197755SDaniel Borkmann 
815b2197755SDaniel Borkmann static int __init bpf_init(void)
816b2197755SDaniel Borkmann {
817b2197755SDaniel Borkmann 	int ret;
818b2197755SDaniel Borkmann 
819d71fa5c9SAlexei Starovoitov 	mutex_init(&bpf_preload_lock);
820d71fa5c9SAlexei Starovoitov 
821b2197755SDaniel Borkmann 	ret = sysfs_create_mount_point(fs_kobj, "bpf");
822b2197755SDaniel Borkmann 	if (ret)
823b2197755SDaniel Borkmann 		return ret;
824b2197755SDaniel Borkmann 
825b2197755SDaniel Borkmann 	ret = register_filesystem(&bpf_fs_type);
826b2197755SDaniel Borkmann 	if (ret)
827b2197755SDaniel Borkmann 		sysfs_remove_mount_point(fs_kobj, "bpf");
828b2197755SDaniel Borkmann 
829b2197755SDaniel Borkmann 	return ret;
830b2197755SDaniel Borkmann }
831b2197755SDaniel Borkmann fs_initcall(bpf_init);
832