xref: /linux/kernel/bpf/syscall.c (revision 3ad0040573b0c00f88488bc31958acd07a55ee2e)
199c55f7dSAlexei Starovoitov /* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
299c55f7dSAlexei Starovoitov  *
399c55f7dSAlexei Starovoitov  * This program is free software; you can redistribute it and/or
499c55f7dSAlexei Starovoitov  * modify it under the terms of version 2 of the GNU General Public
599c55f7dSAlexei Starovoitov  * License as published by the Free Software Foundation.
699c55f7dSAlexei Starovoitov  *
799c55f7dSAlexei Starovoitov  * This program is distributed in the hope that it will be useful, but
899c55f7dSAlexei Starovoitov  * WITHOUT ANY WARRANTY; without even the implied warranty of
999c55f7dSAlexei Starovoitov  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1099c55f7dSAlexei Starovoitov  * General Public License for more details.
1199c55f7dSAlexei Starovoitov  */
1299c55f7dSAlexei Starovoitov #include <linux/bpf.h>
1399c55f7dSAlexei Starovoitov #include <linux/syscalls.h>
1499c55f7dSAlexei Starovoitov #include <linux/slab.h>
1599c55f7dSAlexei Starovoitov #include <linux/anon_inodes.h>
16db20fd2bSAlexei Starovoitov #include <linux/file.h>
1709756af4SAlexei Starovoitov #include <linux/license.h>
1809756af4SAlexei Starovoitov #include <linux/filter.h>
192541517cSAlexei Starovoitov #include <linux/version.h>
2099c55f7dSAlexei Starovoitov 
2199c55f7dSAlexei Starovoitov static LIST_HEAD(bpf_map_types);
2299c55f7dSAlexei Starovoitov 
2399c55f7dSAlexei Starovoitov static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
2499c55f7dSAlexei Starovoitov {
2599c55f7dSAlexei Starovoitov 	struct bpf_map_type_list *tl;
2699c55f7dSAlexei Starovoitov 	struct bpf_map *map;
2799c55f7dSAlexei Starovoitov 
2899c55f7dSAlexei Starovoitov 	list_for_each_entry(tl, &bpf_map_types, list_node) {
2999c55f7dSAlexei Starovoitov 		if (tl->type == attr->map_type) {
3099c55f7dSAlexei Starovoitov 			map = tl->ops->map_alloc(attr);
3199c55f7dSAlexei Starovoitov 			if (IS_ERR(map))
3299c55f7dSAlexei Starovoitov 				return map;
3399c55f7dSAlexei Starovoitov 			map->ops = tl->ops;
3499c55f7dSAlexei Starovoitov 			map->map_type = attr->map_type;
3599c55f7dSAlexei Starovoitov 			return map;
3699c55f7dSAlexei Starovoitov 		}
3799c55f7dSAlexei Starovoitov 	}
3899c55f7dSAlexei Starovoitov 	return ERR_PTR(-EINVAL);
3999c55f7dSAlexei Starovoitov }
4099c55f7dSAlexei Starovoitov 
4199c55f7dSAlexei Starovoitov /* boot time registration of different map implementations */
4299c55f7dSAlexei Starovoitov void bpf_register_map_type(struct bpf_map_type_list *tl)
4399c55f7dSAlexei Starovoitov {
4499c55f7dSAlexei Starovoitov 	list_add(&tl->list_node, &bpf_map_types);
4599c55f7dSAlexei Starovoitov }
4699c55f7dSAlexei Starovoitov 
4799c55f7dSAlexei Starovoitov /* called from workqueue */
4899c55f7dSAlexei Starovoitov static void bpf_map_free_deferred(struct work_struct *work)
4999c55f7dSAlexei Starovoitov {
5099c55f7dSAlexei Starovoitov 	struct bpf_map *map = container_of(work, struct bpf_map, work);
5199c55f7dSAlexei Starovoitov 
5299c55f7dSAlexei Starovoitov 	/* implementation dependent freeing */
5399c55f7dSAlexei Starovoitov 	map->ops->map_free(map);
5499c55f7dSAlexei Starovoitov }
5599c55f7dSAlexei Starovoitov 
5699c55f7dSAlexei Starovoitov /* decrement map refcnt and schedule it for freeing via workqueue
5799c55f7dSAlexei Starovoitov  * (unrelying map implementation ops->map_free() might sleep)
5899c55f7dSAlexei Starovoitov  */
5999c55f7dSAlexei Starovoitov void bpf_map_put(struct bpf_map *map)
6099c55f7dSAlexei Starovoitov {
6199c55f7dSAlexei Starovoitov 	if (atomic_dec_and_test(&map->refcnt)) {
6299c55f7dSAlexei Starovoitov 		INIT_WORK(&map->work, bpf_map_free_deferred);
6399c55f7dSAlexei Starovoitov 		schedule_work(&map->work);
6499c55f7dSAlexei Starovoitov 	}
6599c55f7dSAlexei Starovoitov }
6699c55f7dSAlexei Starovoitov 
6799c55f7dSAlexei Starovoitov static int bpf_map_release(struct inode *inode, struct file *filp)
6899c55f7dSAlexei Starovoitov {
6999c55f7dSAlexei Starovoitov 	struct bpf_map *map = filp->private_data;
7099c55f7dSAlexei Starovoitov 
7104fd61abSAlexei Starovoitov 	if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
7204fd61abSAlexei Starovoitov 		/* prog_array stores refcnt-ed bpf_prog pointers
7304fd61abSAlexei Starovoitov 		 * release them all when user space closes prog_array_fd
7404fd61abSAlexei Starovoitov 		 */
752a36f0b9SWang Nan 		bpf_fd_array_map_clear(map);
7604fd61abSAlexei Starovoitov 
7799c55f7dSAlexei Starovoitov 	bpf_map_put(map);
7899c55f7dSAlexei Starovoitov 	return 0;
7999c55f7dSAlexei Starovoitov }
8099c55f7dSAlexei Starovoitov 
8199c55f7dSAlexei Starovoitov static const struct file_operations bpf_map_fops = {
8299c55f7dSAlexei Starovoitov 	.release = bpf_map_release,
8399c55f7dSAlexei Starovoitov };
8499c55f7dSAlexei Starovoitov 
8599c55f7dSAlexei Starovoitov /* helper macro to check that unused fields 'union bpf_attr' are zero */
8699c55f7dSAlexei Starovoitov #define CHECK_ATTR(CMD) \
8799c55f7dSAlexei Starovoitov 	memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
8899c55f7dSAlexei Starovoitov 		   sizeof(attr->CMD##_LAST_FIELD), 0, \
8999c55f7dSAlexei Starovoitov 		   sizeof(*attr) - \
9099c55f7dSAlexei Starovoitov 		   offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
9199c55f7dSAlexei Starovoitov 		   sizeof(attr->CMD##_LAST_FIELD)) != NULL
9299c55f7dSAlexei Starovoitov 
9399c55f7dSAlexei Starovoitov #define BPF_MAP_CREATE_LAST_FIELD max_entries
9499c55f7dSAlexei Starovoitov /* called via syscall */
9599c55f7dSAlexei Starovoitov static int map_create(union bpf_attr *attr)
9699c55f7dSAlexei Starovoitov {
9799c55f7dSAlexei Starovoitov 	struct bpf_map *map;
9899c55f7dSAlexei Starovoitov 	int err;
9999c55f7dSAlexei Starovoitov 
10099c55f7dSAlexei Starovoitov 	err = CHECK_ATTR(BPF_MAP_CREATE);
10199c55f7dSAlexei Starovoitov 	if (err)
10299c55f7dSAlexei Starovoitov 		return -EINVAL;
10399c55f7dSAlexei Starovoitov 
10499c55f7dSAlexei Starovoitov 	/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
10599c55f7dSAlexei Starovoitov 	map = find_and_alloc_map(attr);
10699c55f7dSAlexei Starovoitov 	if (IS_ERR(map))
10799c55f7dSAlexei Starovoitov 		return PTR_ERR(map);
10899c55f7dSAlexei Starovoitov 
10999c55f7dSAlexei Starovoitov 	atomic_set(&map->refcnt, 1);
11099c55f7dSAlexei Starovoitov 
11199c55f7dSAlexei Starovoitov 	err = anon_inode_getfd("bpf-map", &bpf_map_fops, map, O_RDWR | O_CLOEXEC);
11299c55f7dSAlexei Starovoitov 
11399c55f7dSAlexei Starovoitov 	if (err < 0)
11499c55f7dSAlexei Starovoitov 		/* failed to allocate fd */
11599c55f7dSAlexei Starovoitov 		goto free_map;
11699c55f7dSAlexei Starovoitov 
11799c55f7dSAlexei Starovoitov 	return err;
11899c55f7dSAlexei Starovoitov 
11999c55f7dSAlexei Starovoitov free_map:
12099c55f7dSAlexei Starovoitov 	map->ops->map_free(map);
12199c55f7dSAlexei Starovoitov 	return err;
12299c55f7dSAlexei Starovoitov }
12399c55f7dSAlexei Starovoitov 
124db20fd2bSAlexei Starovoitov /* if error is returned, fd is released.
125db20fd2bSAlexei Starovoitov  * On success caller should complete fd access with matching fdput()
126db20fd2bSAlexei Starovoitov  */
127db20fd2bSAlexei Starovoitov struct bpf_map *bpf_map_get(struct fd f)
128db20fd2bSAlexei Starovoitov {
129db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
130db20fd2bSAlexei Starovoitov 
131db20fd2bSAlexei Starovoitov 	if (!f.file)
132db20fd2bSAlexei Starovoitov 		return ERR_PTR(-EBADF);
133db20fd2bSAlexei Starovoitov 
134db20fd2bSAlexei Starovoitov 	if (f.file->f_op != &bpf_map_fops) {
135db20fd2bSAlexei Starovoitov 		fdput(f);
136db20fd2bSAlexei Starovoitov 		return ERR_PTR(-EINVAL);
137db20fd2bSAlexei Starovoitov 	}
138db20fd2bSAlexei Starovoitov 
139db20fd2bSAlexei Starovoitov 	map = f.file->private_data;
140db20fd2bSAlexei Starovoitov 
141db20fd2bSAlexei Starovoitov 	return map;
142db20fd2bSAlexei Starovoitov }
143db20fd2bSAlexei Starovoitov 
144db20fd2bSAlexei Starovoitov /* helper to convert user pointers passed inside __aligned_u64 fields */
145db20fd2bSAlexei Starovoitov static void __user *u64_to_ptr(__u64 val)
146db20fd2bSAlexei Starovoitov {
147db20fd2bSAlexei Starovoitov 	return (void __user *) (unsigned long) val;
148db20fd2bSAlexei Starovoitov }
149db20fd2bSAlexei Starovoitov 
150db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
151db20fd2bSAlexei Starovoitov #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
152db20fd2bSAlexei Starovoitov 
153db20fd2bSAlexei Starovoitov static int map_lookup_elem(union bpf_attr *attr)
154db20fd2bSAlexei Starovoitov {
155db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
156db20fd2bSAlexei Starovoitov 	void __user *uvalue = u64_to_ptr(attr->value);
157db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
158db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
1598ebe667cSAlexei Starovoitov 	void *key, *value, *ptr;
160592867bfSDaniel Borkmann 	struct fd f;
161db20fd2bSAlexei Starovoitov 	int err;
162db20fd2bSAlexei Starovoitov 
163db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
164db20fd2bSAlexei Starovoitov 		return -EINVAL;
165db20fd2bSAlexei Starovoitov 
166592867bfSDaniel Borkmann 	f = fdget(ufd);
167db20fd2bSAlexei Starovoitov 	map = bpf_map_get(f);
168db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
169db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
170db20fd2bSAlexei Starovoitov 
171db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
172db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
173db20fd2bSAlexei Starovoitov 	if (!key)
174db20fd2bSAlexei Starovoitov 		goto err_put;
175db20fd2bSAlexei Starovoitov 
176db20fd2bSAlexei Starovoitov 	err = -EFAULT;
177db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
178db20fd2bSAlexei Starovoitov 		goto free_key;
179db20fd2bSAlexei Starovoitov 
1808ebe667cSAlexei Starovoitov 	err = -ENOMEM;
1818ebe667cSAlexei Starovoitov 	value = kmalloc(map->value_size, GFP_USER);
182db20fd2bSAlexei Starovoitov 	if (!value)
1838ebe667cSAlexei Starovoitov 		goto free_key;
1848ebe667cSAlexei Starovoitov 
1858ebe667cSAlexei Starovoitov 	rcu_read_lock();
1868ebe667cSAlexei Starovoitov 	ptr = map->ops->map_lookup_elem(map, key);
1878ebe667cSAlexei Starovoitov 	if (ptr)
1888ebe667cSAlexei Starovoitov 		memcpy(value, ptr, map->value_size);
1898ebe667cSAlexei Starovoitov 	rcu_read_unlock();
1908ebe667cSAlexei Starovoitov 
1918ebe667cSAlexei Starovoitov 	err = -ENOENT;
1928ebe667cSAlexei Starovoitov 	if (!ptr)
1938ebe667cSAlexei Starovoitov 		goto free_value;
194db20fd2bSAlexei Starovoitov 
195db20fd2bSAlexei Starovoitov 	err = -EFAULT;
196db20fd2bSAlexei Starovoitov 	if (copy_to_user(uvalue, value, map->value_size) != 0)
1978ebe667cSAlexei Starovoitov 		goto free_value;
198db20fd2bSAlexei Starovoitov 
199db20fd2bSAlexei Starovoitov 	err = 0;
200db20fd2bSAlexei Starovoitov 
2018ebe667cSAlexei Starovoitov free_value:
2028ebe667cSAlexei Starovoitov 	kfree(value);
203db20fd2bSAlexei Starovoitov free_key:
204db20fd2bSAlexei Starovoitov 	kfree(key);
205db20fd2bSAlexei Starovoitov err_put:
206db20fd2bSAlexei Starovoitov 	fdput(f);
207db20fd2bSAlexei Starovoitov 	return err;
208db20fd2bSAlexei Starovoitov }
209db20fd2bSAlexei Starovoitov 
2103274f520SAlexei Starovoitov #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
211db20fd2bSAlexei Starovoitov 
212db20fd2bSAlexei Starovoitov static int map_update_elem(union bpf_attr *attr)
213db20fd2bSAlexei Starovoitov {
214db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
215db20fd2bSAlexei Starovoitov 	void __user *uvalue = u64_to_ptr(attr->value);
216db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
217db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
218db20fd2bSAlexei Starovoitov 	void *key, *value;
219592867bfSDaniel Borkmann 	struct fd f;
220db20fd2bSAlexei Starovoitov 	int err;
221db20fd2bSAlexei Starovoitov 
222db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
223db20fd2bSAlexei Starovoitov 		return -EINVAL;
224db20fd2bSAlexei Starovoitov 
225592867bfSDaniel Borkmann 	f = fdget(ufd);
226db20fd2bSAlexei Starovoitov 	map = bpf_map_get(f);
227db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
228db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
229db20fd2bSAlexei Starovoitov 
230db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
231db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
232db20fd2bSAlexei Starovoitov 	if (!key)
233db20fd2bSAlexei Starovoitov 		goto err_put;
234db20fd2bSAlexei Starovoitov 
235db20fd2bSAlexei Starovoitov 	err = -EFAULT;
236db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
237db20fd2bSAlexei Starovoitov 		goto free_key;
238db20fd2bSAlexei Starovoitov 
239db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
240db20fd2bSAlexei Starovoitov 	value = kmalloc(map->value_size, GFP_USER);
241db20fd2bSAlexei Starovoitov 	if (!value)
242db20fd2bSAlexei Starovoitov 		goto free_key;
243db20fd2bSAlexei Starovoitov 
244db20fd2bSAlexei Starovoitov 	err = -EFAULT;
245db20fd2bSAlexei Starovoitov 	if (copy_from_user(value, uvalue, map->value_size) != 0)
246db20fd2bSAlexei Starovoitov 		goto free_value;
247db20fd2bSAlexei Starovoitov 
248db20fd2bSAlexei Starovoitov 	/* eBPF program that use maps are running under rcu_read_lock(),
249db20fd2bSAlexei Starovoitov 	 * therefore all map accessors rely on this fact, so do the same here
250db20fd2bSAlexei Starovoitov 	 */
251db20fd2bSAlexei Starovoitov 	rcu_read_lock();
2523274f520SAlexei Starovoitov 	err = map->ops->map_update_elem(map, key, value, attr->flags);
253db20fd2bSAlexei Starovoitov 	rcu_read_unlock();
254db20fd2bSAlexei Starovoitov 
255db20fd2bSAlexei Starovoitov free_value:
256db20fd2bSAlexei Starovoitov 	kfree(value);
257db20fd2bSAlexei Starovoitov free_key:
258db20fd2bSAlexei Starovoitov 	kfree(key);
259db20fd2bSAlexei Starovoitov err_put:
260db20fd2bSAlexei Starovoitov 	fdput(f);
261db20fd2bSAlexei Starovoitov 	return err;
262db20fd2bSAlexei Starovoitov }
263db20fd2bSAlexei Starovoitov 
264db20fd2bSAlexei Starovoitov #define BPF_MAP_DELETE_ELEM_LAST_FIELD key
265db20fd2bSAlexei Starovoitov 
266db20fd2bSAlexei Starovoitov static int map_delete_elem(union bpf_attr *attr)
267db20fd2bSAlexei Starovoitov {
268db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
269db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
270db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
271592867bfSDaniel Borkmann 	struct fd f;
272db20fd2bSAlexei Starovoitov 	void *key;
273db20fd2bSAlexei Starovoitov 	int err;
274db20fd2bSAlexei Starovoitov 
275db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
276db20fd2bSAlexei Starovoitov 		return -EINVAL;
277db20fd2bSAlexei Starovoitov 
278592867bfSDaniel Borkmann 	f = fdget(ufd);
279db20fd2bSAlexei Starovoitov 	map = bpf_map_get(f);
280db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
281db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
282db20fd2bSAlexei Starovoitov 
283db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
284db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
285db20fd2bSAlexei Starovoitov 	if (!key)
286db20fd2bSAlexei Starovoitov 		goto err_put;
287db20fd2bSAlexei Starovoitov 
288db20fd2bSAlexei Starovoitov 	err = -EFAULT;
289db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
290db20fd2bSAlexei Starovoitov 		goto free_key;
291db20fd2bSAlexei Starovoitov 
292db20fd2bSAlexei Starovoitov 	rcu_read_lock();
293db20fd2bSAlexei Starovoitov 	err = map->ops->map_delete_elem(map, key);
294db20fd2bSAlexei Starovoitov 	rcu_read_unlock();
295db20fd2bSAlexei Starovoitov 
296db20fd2bSAlexei Starovoitov free_key:
297db20fd2bSAlexei Starovoitov 	kfree(key);
298db20fd2bSAlexei Starovoitov err_put:
299db20fd2bSAlexei Starovoitov 	fdput(f);
300db20fd2bSAlexei Starovoitov 	return err;
301db20fd2bSAlexei Starovoitov }
302db20fd2bSAlexei Starovoitov 
303db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
304db20fd2bSAlexei Starovoitov #define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
305db20fd2bSAlexei Starovoitov 
306db20fd2bSAlexei Starovoitov static int map_get_next_key(union bpf_attr *attr)
307db20fd2bSAlexei Starovoitov {
308db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
309db20fd2bSAlexei Starovoitov 	void __user *unext_key = u64_to_ptr(attr->next_key);
310db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
311db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
312db20fd2bSAlexei Starovoitov 	void *key, *next_key;
313592867bfSDaniel Borkmann 	struct fd f;
314db20fd2bSAlexei Starovoitov 	int err;
315db20fd2bSAlexei Starovoitov 
316db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
317db20fd2bSAlexei Starovoitov 		return -EINVAL;
318db20fd2bSAlexei Starovoitov 
319592867bfSDaniel Borkmann 	f = fdget(ufd);
320db20fd2bSAlexei Starovoitov 	map = bpf_map_get(f);
321db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
322db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
323db20fd2bSAlexei Starovoitov 
324db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
325db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
326db20fd2bSAlexei Starovoitov 	if (!key)
327db20fd2bSAlexei Starovoitov 		goto err_put;
328db20fd2bSAlexei Starovoitov 
329db20fd2bSAlexei Starovoitov 	err = -EFAULT;
330db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
331db20fd2bSAlexei Starovoitov 		goto free_key;
332db20fd2bSAlexei Starovoitov 
333db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
334db20fd2bSAlexei Starovoitov 	next_key = kmalloc(map->key_size, GFP_USER);
335db20fd2bSAlexei Starovoitov 	if (!next_key)
336db20fd2bSAlexei Starovoitov 		goto free_key;
337db20fd2bSAlexei Starovoitov 
338db20fd2bSAlexei Starovoitov 	rcu_read_lock();
339db20fd2bSAlexei Starovoitov 	err = map->ops->map_get_next_key(map, key, next_key);
340db20fd2bSAlexei Starovoitov 	rcu_read_unlock();
341db20fd2bSAlexei Starovoitov 	if (err)
342db20fd2bSAlexei Starovoitov 		goto free_next_key;
343db20fd2bSAlexei Starovoitov 
344db20fd2bSAlexei Starovoitov 	err = -EFAULT;
345db20fd2bSAlexei Starovoitov 	if (copy_to_user(unext_key, next_key, map->key_size) != 0)
346db20fd2bSAlexei Starovoitov 		goto free_next_key;
347db20fd2bSAlexei Starovoitov 
348db20fd2bSAlexei Starovoitov 	err = 0;
349db20fd2bSAlexei Starovoitov 
350db20fd2bSAlexei Starovoitov free_next_key:
351db20fd2bSAlexei Starovoitov 	kfree(next_key);
352db20fd2bSAlexei Starovoitov free_key:
353db20fd2bSAlexei Starovoitov 	kfree(key);
354db20fd2bSAlexei Starovoitov err_put:
355db20fd2bSAlexei Starovoitov 	fdput(f);
356db20fd2bSAlexei Starovoitov 	return err;
357db20fd2bSAlexei Starovoitov }
358db20fd2bSAlexei Starovoitov 
35909756af4SAlexei Starovoitov static LIST_HEAD(bpf_prog_types);
36009756af4SAlexei Starovoitov 
36109756af4SAlexei Starovoitov static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
36209756af4SAlexei Starovoitov {
36309756af4SAlexei Starovoitov 	struct bpf_prog_type_list *tl;
36409756af4SAlexei Starovoitov 
36509756af4SAlexei Starovoitov 	list_for_each_entry(tl, &bpf_prog_types, list_node) {
36609756af4SAlexei Starovoitov 		if (tl->type == type) {
36709756af4SAlexei Starovoitov 			prog->aux->ops = tl->ops;
36824701eceSDaniel Borkmann 			prog->type = type;
36909756af4SAlexei Starovoitov 			return 0;
37009756af4SAlexei Starovoitov 		}
37109756af4SAlexei Starovoitov 	}
37224701eceSDaniel Borkmann 
37309756af4SAlexei Starovoitov 	return -EINVAL;
37409756af4SAlexei Starovoitov }
37509756af4SAlexei Starovoitov 
37609756af4SAlexei Starovoitov void bpf_register_prog_type(struct bpf_prog_type_list *tl)
37709756af4SAlexei Starovoitov {
37809756af4SAlexei Starovoitov 	list_add(&tl->list_node, &bpf_prog_types);
37909756af4SAlexei Starovoitov }
38009756af4SAlexei Starovoitov 
3810a542a86SAlexei Starovoitov /* fixup insn->imm field of bpf_call instructions:
3820a542a86SAlexei Starovoitov  * if (insn->imm == BPF_FUNC_map_lookup_elem)
3830a542a86SAlexei Starovoitov  *      insn->imm = bpf_map_lookup_elem - __bpf_call_base;
3840a542a86SAlexei Starovoitov  * else if (insn->imm == BPF_FUNC_map_update_elem)
3850a542a86SAlexei Starovoitov  *      insn->imm = bpf_map_update_elem - __bpf_call_base;
3860a542a86SAlexei Starovoitov  * else ...
3870a542a86SAlexei Starovoitov  *
3880a542a86SAlexei Starovoitov  * this function is called after eBPF program passed verification
3890a542a86SAlexei Starovoitov  */
3900a542a86SAlexei Starovoitov static void fixup_bpf_calls(struct bpf_prog *prog)
3910a542a86SAlexei Starovoitov {
3920a542a86SAlexei Starovoitov 	const struct bpf_func_proto *fn;
3930a542a86SAlexei Starovoitov 	int i;
3940a542a86SAlexei Starovoitov 
3950a542a86SAlexei Starovoitov 	for (i = 0; i < prog->len; i++) {
3960a542a86SAlexei Starovoitov 		struct bpf_insn *insn = &prog->insnsi[i];
3970a542a86SAlexei Starovoitov 
3980a542a86SAlexei Starovoitov 		if (insn->code == (BPF_JMP | BPF_CALL)) {
3990a542a86SAlexei Starovoitov 			/* we reach here when program has bpf_call instructions
4000a542a86SAlexei Starovoitov 			 * and it passed bpf_check(), means that
4010a542a86SAlexei Starovoitov 			 * ops->get_func_proto must have been supplied, check it
4020a542a86SAlexei Starovoitov 			 */
4030a542a86SAlexei Starovoitov 			BUG_ON(!prog->aux->ops->get_func_proto);
4040a542a86SAlexei Starovoitov 
405c46646d0SDaniel Borkmann 			if (insn->imm == BPF_FUNC_get_route_realm)
406c46646d0SDaniel Borkmann 				prog->dst_needed = 1;
407*3ad00405SDaniel Borkmann 			if (insn->imm == BPF_FUNC_get_prandom_u32)
408*3ad00405SDaniel Borkmann 				bpf_user_rnd_init_once();
40904fd61abSAlexei Starovoitov 			if (insn->imm == BPF_FUNC_tail_call) {
41004fd61abSAlexei Starovoitov 				/* mark bpf_tail_call as different opcode
41104fd61abSAlexei Starovoitov 				 * to avoid conditional branch in
41204fd61abSAlexei Starovoitov 				 * interpeter for every normal call
41304fd61abSAlexei Starovoitov 				 * and to prevent accidental JITing by
41404fd61abSAlexei Starovoitov 				 * JIT compiler that doesn't support
41504fd61abSAlexei Starovoitov 				 * bpf_tail_call yet
41604fd61abSAlexei Starovoitov 				 */
41704fd61abSAlexei Starovoitov 				insn->imm = 0;
41804fd61abSAlexei Starovoitov 				insn->code |= BPF_X;
41904fd61abSAlexei Starovoitov 				continue;
42004fd61abSAlexei Starovoitov 			}
42104fd61abSAlexei Starovoitov 
4220a542a86SAlexei Starovoitov 			fn = prog->aux->ops->get_func_proto(insn->imm);
4230a542a86SAlexei Starovoitov 			/* all functions that have prototype and verifier allowed
4240a542a86SAlexei Starovoitov 			 * programs to call them, must be real in-kernel functions
4250a542a86SAlexei Starovoitov 			 */
4260a542a86SAlexei Starovoitov 			BUG_ON(!fn->func);
4270a542a86SAlexei Starovoitov 			insn->imm = fn->func - __bpf_call_base;
4280a542a86SAlexei Starovoitov 		}
4290a542a86SAlexei Starovoitov 	}
4300a542a86SAlexei Starovoitov }
4310a542a86SAlexei Starovoitov 
43209756af4SAlexei Starovoitov /* drop refcnt on maps used by eBPF program and free auxilary data */
43309756af4SAlexei Starovoitov static void free_used_maps(struct bpf_prog_aux *aux)
43409756af4SAlexei Starovoitov {
43509756af4SAlexei Starovoitov 	int i;
43609756af4SAlexei Starovoitov 
43709756af4SAlexei Starovoitov 	for (i = 0; i < aux->used_map_cnt; i++)
43809756af4SAlexei Starovoitov 		bpf_map_put(aux->used_maps[i]);
43909756af4SAlexei Starovoitov 
44009756af4SAlexei Starovoitov 	kfree(aux->used_maps);
44109756af4SAlexei Starovoitov }
44209756af4SAlexei Starovoitov 
443abf2e7d6SAlexei Starovoitov static void __prog_put_rcu(struct rcu_head *rcu)
444abf2e7d6SAlexei Starovoitov {
445abf2e7d6SAlexei Starovoitov 	struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
446abf2e7d6SAlexei Starovoitov 
447abf2e7d6SAlexei Starovoitov 	free_used_maps(aux);
448abf2e7d6SAlexei Starovoitov 	bpf_prog_free(aux->prog);
449abf2e7d6SAlexei Starovoitov }
450abf2e7d6SAlexei Starovoitov 
451abf2e7d6SAlexei Starovoitov /* version of bpf_prog_put() that is called after a grace period */
452abf2e7d6SAlexei Starovoitov void bpf_prog_put_rcu(struct bpf_prog *prog)
453abf2e7d6SAlexei Starovoitov {
454abf2e7d6SAlexei Starovoitov 	if (atomic_dec_and_test(&prog->aux->refcnt)) {
455abf2e7d6SAlexei Starovoitov 		prog->aux->prog = prog;
456abf2e7d6SAlexei Starovoitov 		call_rcu(&prog->aux->rcu, __prog_put_rcu);
457abf2e7d6SAlexei Starovoitov 	}
458abf2e7d6SAlexei Starovoitov }
459abf2e7d6SAlexei Starovoitov 
46009756af4SAlexei Starovoitov void bpf_prog_put(struct bpf_prog *prog)
46109756af4SAlexei Starovoitov {
46209756af4SAlexei Starovoitov 	if (atomic_dec_and_test(&prog->aux->refcnt)) {
46309756af4SAlexei Starovoitov 		free_used_maps(prog->aux);
46409756af4SAlexei Starovoitov 		bpf_prog_free(prog);
46509756af4SAlexei Starovoitov 	}
46609756af4SAlexei Starovoitov }
467e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_put);
46809756af4SAlexei Starovoitov 
46909756af4SAlexei Starovoitov static int bpf_prog_release(struct inode *inode, struct file *filp)
47009756af4SAlexei Starovoitov {
47109756af4SAlexei Starovoitov 	struct bpf_prog *prog = filp->private_data;
47209756af4SAlexei Starovoitov 
473abf2e7d6SAlexei Starovoitov 	bpf_prog_put_rcu(prog);
47409756af4SAlexei Starovoitov 	return 0;
47509756af4SAlexei Starovoitov }
47609756af4SAlexei Starovoitov 
47709756af4SAlexei Starovoitov static const struct file_operations bpf_prog_fops = {
47809756af4SAlexei Starovoitov         .release = bpf_prog_release,
47909756af4SAlexei Starovoitov };
48009756af4SAlexei Starovoitov 
48109756af4SAlexei Starovoitov static struct bpf_prog *get_prog(struct fd f)
48209756af4SAlexei Starovoitov {
48309756af4SAlexei Starovoitov 	struct bpf_prog *prog;
48409756af4SAlexei Starovoitov 
48509756af4SAlexei Starovoitov 	if (!f.file)
48609756af4SAlexei Starovoitov 		return ERR_PTR(-EBADF);
48709756af4SAlexei Starovoitov 
48809756af4SAlexei Starovoitov 	if (f.file->f_op != &bpf_prog_fops) {
48909756af4SAlexei Starovoitov 		fdput(f);
49009756af4SAlexei Starovoitov 		return ERR_PTR(-EINVAL);
49109756af4SAlexei Starovoitov 	}
49209756af4SAlexei Starovoitov 
49309756af4SAlexei Starovoitov 	prog = f.file->private_data;
49409756af4SAlexei Starovoitov 
49509756af4SAlexei Starovoitov 	return prog;
49609756af4SAlexei Starovoitov }
49709756af4SAlexei Starovoitov 
49809756af4SAlexei Starovoitov /* called by sockets/tracing/seccomp before attaching program to an event
49909756af4SAlexei Starovoitov  * pairs with bpf_prog_put()
50009756af4SAlexei Starovoitov  */
50109756af4SAlexei Starovoitov struct bpf_prog *bpf_prog_get(u32 ufd)
50209756af4SAlexei Starovoitov {
50309756af4SAlexei Starovoitov 	struct fd f = fdget(ufd);
50409756af4SAlexei Starovoitov 	struct bpf_prog *prog;
50509756af4SAlexei Starovoitov 
50609756af4SAlexei Starovoitov 	prog = get_prog(f);
50709756af4SAlexei Starovoitov 
50809756af4SAlexei Starovoitov 	if (IS_ERR(prog))
50909756af4SAlexei Starovoitov 		return prog;
51009756af4SAlexei Starovoitov 
51109756af4SAlexei Starovoitov 	atomic_inc(&prog->aux->refcnt);
51209756af4SAlexei Starovoitov 	fdput(f);
51309756af4SAlexei Starovoitov 	return prog;
51409756af4SAlexei Starovoitov }
515e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_get);
51609756af4SAlexei Starovoitov 
51709756af4SAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
5182541517cSAlexei Starovoitov #define	BPF_PROG_LOAD_LAST_FIELD kern_version
51909756af4SAlexei Starovoitov 
52009756af4SAlexei Starovoitov static int bpf_prog_load(union bpf_attr *attr)
52109756af4SAlexei Starovoitov {
52209756af4SAlexei Starovoitov 	enum bpf_prog_type type = attr->prog_type;
52309756af4SAlexei Starovoitov 	struct bpf_prog *prog;
52409756af4SAlexei Starovoitov 	int err;
52509756af4SAlexei Starovoitov 	char license[128];
52609756af4SAlexei Starovoitov 	bool is_gpl;
52709756af4SAlexei Starovoitov 
52809756af4SAlexei Starovoitov 	if (CHECK_ATTR(BPF_PROG_LOAD))
52909756af4SAlexei Starovoitov 		return -EINVAL;
53009756af4SAlexei Starovoitov 
53109756af4SAlexei Starovoitov 	/* copy eBPF program license from user space */
53209756af4SAlexei Starovoitov 	if (strncpy_from_user(license, u64_to_ptr(attr->license),
53309756af4SAlexei Starovoitov 			      sizeof(license) - 1) < 0)
53409756af4SAlexei Starovoitov 		return -EFAULT;
53509756af4SAlexei Starovoitov 	license[sizeof(license) - 1] = 0;
53609756af4SAlexei Starovoitov 
53709756af4SAlexei Starovoitov 	/* eBPF programs must be GPL compatible to use GPL-ed functions */
53809756af4SAlexei Starovoitov 	is_gpl = license_is_gpl_compatible(license);
53909756af4SAlexei Starovoitov 
54009756af4SAlexei Starovoitov 	if (attr->insn_cnt >= BPF_MAXINSNS)
54109756af4SAlexei Starovoitov 		return -EINVAL;
54209756af4SAlexei Starovoitov 
5432541517cSAlexei Starovoitov 	if (type == BPF_PROG_TYPE_KPROBE &&
5442541517cSAlexei Starovoitov 	    attr->kern_version != LINUX_VERSION_CODE)
5452541517cSAlexei Starovoitov 		return -EINVAL;
5462541517cSAlexei Starovoitov 
54709756af4SAlexei Starovoitov 	/* plain bpf_prog allocation */
54809756af4SAlexei Starovoitov 	prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
54909756af4SAlexei Starovoitov 	if (!prog)
55009756af4SAlexei Starovoitov 		return -ENOMEM;
55109756af4SAlexei Starovoitov 
55209756af4SAlexei Starovoitov 	prog->len = attr->insn_cnt;
55309756af4SAlexei Starovoitov 
55409756af4SAlexei Starovoitov 	err = -EFAULT;
55509756af4SAlexei Starovoitov 	if (copy_from_user(prog->insns, u64_to_ptr(attr->insns),
55609756af4SAlexei Starovoitov 			   prog->len * sizeof(struct bpf_insn)) != 0)
55709756af4SAlexei Starovoitov 		goto free_prog;
55809756af4SAlexei Starovoitov 
55909756af4SAlexei Starovoitov 	prog->orig_prog = NULL;
560a91263d5SDaniel Borkmann 	prog->jited = 0;
56109756af4SAlexei Starovoitov 
56209756af4SAlexei Starovoitov 	atomic_set(&prog->aux->refcnt, 1);
563a91263d5SDaniel Borkmann 	prog->gpl_compatible = is_gpl ? 1 : 0;
56409756af4SAlexei Starovoitov 
56509756af4SAlexei Starovoitov 	/* find program type: socket_filter vs tracing_filter */
56609756af4SAlexei Starovoitov 	err = find_prog_type(type, prog);
56709756af4SAlexei Starovoitov 	if (err < 0)
56809756af4SAlexei Starovoitov 		goto free_prog;
56909756af4SAlexei Starovoitov 
57009756af4SAlexei Starovoitov 	/* run eBPF verifier */
5719bac3d6dSAlexei Starovoitov 	err = bpf_check(&prog, attr);
57209756af4SAlexei Starovoitov 	if (err < 0)
57309756af4SAlexei Starovoitov 		goto free_used_maps;
57409756af4SAlexei Starovoitov 
5750a542a86SAlexei Starovoitov 	/* fixup BPF_CALL->imm field */
5760a542a86SAlexei Starovoitov 	fixup_bpf_calls(prog);
5770a542a86SAlexei Starovoitov 
57809756af4SAlexei Starovoitov 	/* eBPF program is ready to be JITed */
57904fd61abSAlexei Starovoitov 	err = bpf_prog_select_runtime(prog);
58004fd61abSAlexei Starovoitov 	if (err < 0)
58104fd61abSAlexei Starovoitov 		goto free_used_maps;
58209756af4SAlexei Starovoitov 
58309756af4SAlexei Starovoitov 	err = anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog, O_RDWR | O_CLOEXEC);
58409756af4SAlexei Starovoitov 	if (err < 0)
58509756af4SAlexei Starovoitov 		/* failed to allocate fd */
58609756af4SAlexei Starovoitov 		goto free_used_maps;
58709756af4SAlexei Starovoitov 
58809756af4SAlexei Starovoitov 	return err;
58909756af4SAlexei Starovoitov 
59009756af4SAlexei Starovoitov free_used_maps:
59109756af4SAlexei Starovoitov 	free_used_maps(prog->aux);
59209756af4SAlexei Starovoitov free_prog:
59309756af4SAlexei Starovoitov 	bpf_prog_free(prog);
59409756af4SAlexei Starovoitov 	return err;
59509756af4SAlexei Starovoitov }
59609756af4SAlexei Starovoitov 
59799c55f7dSAlexei Starovoitov SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
59899c55f7dSAlexei Starovoitov {
59999c55f7dSAlexei Starovoitov 	union bpf_attr attr = {};
60099c55f7dSAlexei Starovoitov 	int err;
60199c55f7dSAlexei Starovoitov 
60299c55f7dSAlexei Starovoitov 	/* the syscall is limited to root temporarily. This restriction will be
60399c55f7dSAlexei Starovoitov 	 * lifted when security audit is clean. Note that eBPF+tracing must have
60499c55f7dSAlexei Starovoitov 	 * this restriction, since it may pass kernel data to user space
60599c55f7dSAlexei Starovoitov 	 */
60699c55f7dSAlexei Starovoitov 	if (!capable(CAP_SYS_ADMIN))
60799c55f7dSAlexei Starovoitov 		return -EPERM;
60899c55f7dSAlexei Starovoitov 
60999c55f7dSAlexei Starovoitov 	if (!access_ok(VERIFY_READ, uattr, 1))
61099c55f7dSAlexei Starovoitov 		return -EFAULT;
61199c55f7dSAlexei Starovoitov 
61299c55f7dSAlexei Starovoitov 	if (size > PAGE_SIZE)	/* silly large */
61399c55f7dSAlexei Starovoitov 		return -E2BIG;
61499c55f7dSAlexei Starovoitov 
61599c55f7dSAlexei Starovoitov 	/* If we're handed a bigger struct than we know of,
61699c55f7dSAlexei Starovoitov 	 * ensure all the unknown bits are 0 - i.e. new
61799c55f7dSAlexei Starovoitov 	 * user-space does not rely on any kernel feature
61899c55f7dSAlexei Starovoitov 	 * extensions we dont know about yet.
61999c55f7dSAlexei Starovoitov 	 */
62099c55f7dSAlexei Starovoitov 	if (size > sizeof(attr)) {
62199c55f7dSAlexei Starovoitov 		unsigned char __user *addr;
62299c55f7dSAlexei Starovoitov 		unsigned char __user *end;
62399c55f7dSAlexei Starovoitov 		unsigned char val;
62499c55f7dSAlexei Starovoitov 
62599c55f7dSAlexei Starovoitov 		addr = (void __user *)uattr + sizeof(attr);
62699c55f7dSAlexei Starovoitov 		end  = (void __user *)uattr + size;
62799c55f7dSAlexei Starovoitov 
62899c55f7dSAlexei Starovoitov 		for (; addr < end; addr++) {
62999c55f7dSAlexei Starovoitov 			err = get_user(val, addr);
63099c55f7dSAlexei Starovoitov 			if (err)
63199c55f7dSAlexei Starovoitov 				return err;
63299c55f7dSAlexei Starovoitov 			if (val)
63399c55f7dSAlexei Starovoitov 				return -E2BIG;
63499c55f7dSAlexei Starovoitov 		}
63599c55f7dSAlexei Starovoitov 		size = sizeof(attr);
63699c55f7dSAlexei Starovoitov 	}
63799c55f7dSAlexei Starovoitov 
63899c55f7dSAlexei Starovoitov 	/* copy attributes from user space, may be less than sizeof(bpf_attr) */
63999c55f7dSAlexei Starovoitov 	if (copy_from_user(&attr, uattr, size) != 0)
64099c55f7dSAlexei Starovoitov 		return -EFAULT;
64199c55f7dSAlexei Starovoitov 
64299c55f7dSAlexei Starovoitov 	switch (cmd) {
64399c55f7dSAlexei Starovoitov 	case BPF_MAP_CREATE:
64499c55f7dSAlexei Starovoitov 		err = map_create(&attr);
64599c55f7dSAlexei Starovoitov 		break;
646db20fd2bSAlexei Starovoitov 	case BPF_MAP_LOOKUP_ELEM:
647db20fd2bSAlexei Starovoitov 		err = map_lookup_elem(&attr);
648db20fd2bSAlexei Starovoitov 		break;
649db20fd2bSAlexei Starovoitov 	case BPF_MAP_UPDATE_ELEM:
650db20fd2bSAlexei Starovoitov 		err = map_update_elem(&attr);
651db20fd2bSAlexei Starovoitov 		break;
652db20fd2bSAlexei Starovoitov 	case BPF_MAP_DELETE_ELEM:
653db20fd2bSAlexei Starovoitov 		err = map_delete_elem(&attr);
654db20fd2bSAlexei Starovoitov 		break;
655db20fd2bSAlexei Starovoitov 	case BPF_MAP_GET_NEXT_KEY:
656db20fd2bSAlexei Starovoitov 		err = map_get_next_key(&attr);
657db20fd2bSAlexei Starovoitov 		break;
65809756af4SAlexei Starovoitov 	case BPF_PROG_LOAD:
65909756af4SAlexei Starovoitov 		err = bpf_prog_load(&attr);
66009756af4SAlexei Starovoitov 		break;
66199c55f7dSAlexei Starovoitov 	default:
66299c55f7dSAlexei Starovoitov 		err = -EINVAL;
66399c55f7dSAlexei Starovoitov 		break;
66499c55f7dSAlexei Starovoitov 	}
66599c55f7dSAlexei Starovoitov 
66699c55f7dSAlexei Starovoitov 	return err;
66799c55f7dSAlexei Starovoitov }
668