xref: /linux/kernel/bpf/syscall.c (revision d056a788765e67773124f520159185bc89f5d1ad)
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 
21b121d1e7SAlexei Starovoitov DEFINE_PER_CPU(int, bpf_prog_active);
22b121d1e7SAlexei Starovoitov 
231be7f75dSAlexei Starovoitov int sysctl_unprivileged_bpf_disabled __read_mostly;
241be7f75dSAlexei Starovoitov 
2599c55f7dSAlexei Starovoitov static LIST_HEAD(bpf_map_types);
2699c55f7dSAlexei Starovoitov 
2799c55f7dSAlexei Starovoitov static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
2899c55f7dSAlexei Starovoitov {
2999c55f7dSAlexei Starovoitov 	struct bpf_map_type_list *tl;
3099c55f7dSAlexei Starovoitov 	struct bpf_map *map;
3199c55f7dSAlexei Starovoitov 
3299c55f7dSAlexei Starovoitov 	list_for_each_entry(tl, &bpf_map_types, list_node) {
3399c55f7dSAlexei Starovoitov 		if (tl->type == attr->map_type) {
3499c55f7dSAlexei Starovoitov 			map = tl->ops->map_alloc(attr);
3599c55f7dSAlexei Starovoitov 			if (IS_ERR(map))
3699c55f7dSAlexei Starovoitov 				return map;
3799c55f7dSAlexei Starovoitov 			map->ops = tl->ops;
3899c55f7dSAlexei Starovoitov 			map->map_type = attr->map_type;
3999c55f7dSAlexei Starovoitov 			return map;
4099c55f7dSAlexei Starovoitov 		}
4199c55f7dSAlexei Starovoitov 	}
4299c55f7dSAlexei Starovoitov 	return ERR_PTR(-EINVAL);
4399c55f7dSAlexei Starovoitov }
4499c55f7dSAlexei Starovoitov 
4599c55f7dSAlexei Starovoitov /* boot time registration of different map implementations */
4699c55f7dSAlexei Starovoitov void bpf_register_map_type(struct bpf_map_type_list *tl)
4799c55f7dSAlexei Starovoitov {
4899c55f7dSAlexei Starovoitov 	list_add(&tl->list_node, &bpf_map_types);
4999c55f7dSAlexei Starovoitov }
5099c55f7dSAlexei Starovoitov 
516c905981SAlexei Starovoitov int bpf_map_precharge_memlock(u32 pages)
526c905981SAlexei Starovoitov {
536c905981SAlexei Starovoitov 	struct user_struct *user = get_current_user();
546c905981SAlexei Starovoitov 	unsigned long memlock_limit, cur;
556c905981SAlexei Starovoitov 
566c905981SAlexei Starovoitov 	memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
576c905981SAlexei Starovoitov 	cur = atomic_long_read(&user->locked_vm);
586c905981SAlexei Starovoitov 	free_uid(user);
596c905981SAlexei Starovoitov 	if (cur + pages > memlock_limit)
606c905981SAlexei Starovoitov 		return -EPERM;
616c905981SAlexei Starovoitov 	return 0;
626c905981SAlexei Starovoitov }
636c905981SAlexei Starovoitov 
64aaac3ba9SAlexei Starovoitov static int bpf_map_charge_memlock(struct bpf_map *map)
65aaac3ba9SAlexei Starovoitov {
66aaac3ba9SAlexei Starovoitov 	struct user_struct *user = get_current_user();
67aaac3ba9SAlexei Starovoitov 	unsigned long memlock_limit;
68aaac3ba9SAlexei Starovoitov 
69aaac3ba9SAlexei Starovoitov 	memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
70aaac3ba9SAlexei Starovoitov 
71aaac3ba9SAlexei Starovoitov 	atomic_long_add(map->pages, &user->locked_vm);
72aaac3ba9SAlexei Starovoitov 
73aaac3ba9SAlexei Starovoitov 	if (atomic_long_read(&user->locked_vm) > memlock_limit) {
74aaac3ba9SAlexei Starovoitov 		atomic_long_sub(map->pages, &user->locked_vm);
75aaac3ba9SAlexei Starovoitov 		free_uid(user);
76aaac3ba9SAlexei Starovoitov 		return -EPERM;
77aaac3ba9SAlexei Starovoitov 	}
78aaac3ba9SAlexei Starovoitov 	map->user = user;
79aaac3ba9SAlexei Starovoitov 	return 0;
80aaac3ba9SAlexei Starovoitov }
81aaac3ba9SAlexei Starovoitov 
82aaac3ba9SAlexei Starovoitov static void bpf_map_uncharge_memlock(struct bpf_map *map)
83aaac3ba9SAlexei Starovoitov {
84aaac3ba9SAlexei Starovoitov 	struct user_struct *user = map->user;
85aaac3ba9SAlexei Starovoitov 
86aaac3ba9SAlexei Starovoitov 	atomic_long_sub(map->pages, &user->locked_vm);
87aaac3ba9SAlexei Starovoitov 	free_uid(user);
88aaac3ba9SAlexei Starovoitov }
89aaac3ba9SAlexei Starovoitov 
9099c55f7dSAlexei Starovoitov /* called from workqueue */
9199c55f7dSAlexei Starovoitov static void bpf_map_free_deferred(struct work_struct *work)
9299c55f7dSAlexei Starovoitov {
9399c55f7dSAlexei Starovoitov 	struct bpf_map *map = container_of(work, struct bpf_map, work);
9499c55f7dSAlexei Starovoitov 
95aaac3ba9SAlexei Starovoitov 	bpf_map_uncharge_memlock(map);
9699c55f7dSAlexei Starovoitov 	/* implementation dependent freeing */
9799c55f7dSAlexei Starovoitov 	map->ops->map_free(map);
9899c55f7dSAlexei Starovoitov }
9999c55f7dSAlexei Starovoitov 
100c9da161cSDaniel Borkmann static void bpf_map_put_uref(struct bpf_map *map)
101c9da161cSDaniel Borkmann {
102c9da161cSDaniel Borkmann 	if (atomic_dec_and_test(&map->usercnt)) {
103c9da161cSDaniel Borkmann 		if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
104c9da161cSDaniel Borkmann 			bpf_fd_array_map_clear(map);
105c9da161cSDaniel Borkmann 	}
106c9da161cSDaniel Borkmann }
107c9da161cSDaniel Borkmann 
10899c55f7dSAlexei Starovoitov /* decrement map refcnt and schedule it for freeing via workqueue
10999c55f7dSAlexei Starovoitov  * (unrelying map implementation ops->map_free() might sleep)
11099c55f7dSAlexei Starovoitov  */
11199c55f7dSAlexei Starovoitov void bpf_map_put(struct bpf_map *map)
11299c55f7dSAlexei Starovoitov {
11399c55f7dSAlexei Starovoitov 	if (atomic_dec_and_test(&map->refcnt)) {
11499c55f7dSAlexei Starovoitov 		INIT_WORK(&map->work, bpf_map_free_deferred);
11599c55f7dSAlexei Starovoitov 		schedule_work(&map->work);
11699c55f7dSAlexei Starovoitov 	}
11799c55f7dSAlexei Starovoitov }
11899c55f7dSAlexei Starovoitov 
119c9da161cSDaniel Borkmann void bpf_map_put_with_uref(struct bpf_map *map)
120c9da161cSDaniel Borkmann {
121c9da161cSDaniel Borkmann 	bpf_map_put_uref(map);
122c9da161cSDaniel Borkmann 	bpf_map_put(map);
123c9da161cSDaniel Borkmann }
124c9da161cSDaniel Borkmann 
12599c55f7dSAlexei Starovoitov static int bpf_map_release(struct inode *inode, struct file *filp)
12699c55f7dSAlexei Starovoitov {
12761d1b6a4SDaniel Borkmann 	struct bpf_map *map = filp->private_data;
12861d1b6a4SDaniel Borkmann 
12961d1b6a4SDaniel Borkmann 	if (map->ops->map_release)
13061d1b6a4SDaniel Borkmann 		map->ops->map_release(map, filp);
13161d1b6a4SDaniel Borkmann 
13261d1b6a4SDaniel Borkmann 	bpf_map_put_with_uref(map);
13399c55f7dSAlexei Starovoitov 	return 0;
13499c55f7dSAlexei Starovoitov }
13599c55f7dSAlexei Starovoitov 
136f99bf205SDaniel Borkmann #ifdef CONFIG_PROC_FS
137f99bf205SDaniel Borkmann static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
138f99bf205SDaniel Borkmann {
139f99bf205SDaniel Borkmann 	const struct bpf_map *map = filp->private_data;
140f99bf205SDaniel Borkmann 
141f99bf205SDaniel Borkmann 	seq_printf(m,
142f99bf205SDaniel Borkmann 		   "map_type:\t%u\n"
143f99bf205SDaniel Borkmann 		   "key_size:\t%u\n"
144f99bf205SDaniel Borkmann 		   "value_size:\t%u\n"
145322cea2fSDaniel Borkmann 		   "max_entries:\t%u\n"
146322cea2fSDaniel Borkmann 		   "map_flags:\t%#x\n",
147f99bf205SDaniel Borkmann 		   map->map_type,
148f99bf205SDaniel Borkmann 		   map->key_size,
149f99bf205SDaniel Borkmann 		   map->value_size,
150322cea2fSDaniel Borkmann 		   map->max_entries,
151322cea2fSDaniel Borkmann 		   map->map_flags);
152f99bf205SDaniel Borkmann }
153f99bf205SDaniel Borkmann #endif
154f99bf205SDaniel Borkmann 
15599c55f7dSAlexei Starovoitov static const struct file_operations bpf_map_fops = {
156f99bf205SDaniel Borkmann #ifdef CONFIG_PROC_FS
157f99bf205SDaniel Borkmann 	.show_fdinfo	= bpf_map_show_fdinfo,
158f99bf205SDaniel Borkmann #endif
15999c55f7dSAlexei Starovoitov 	.release	= bpf_map_release,
16099c55f7dSAlexei Starovoitov };
16199c55f7dSAlexei Starovoitov 
162b2197755SDaniel Borkmann int bpf_map_new_fd(struct bpf_map *map)
163aa79781bSDaniel Borkmann {
164aa79781bSDaniel Borkmann 	return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
165aa79781bSDaniel Borkmann 				O_RDWR | O_CLOEXEC);
166aa79781bSDaniel Borkmann }
167aa79781bSDaniel Borkmann 
16899c55f7dSAlexei Starovoitov /* helper macro to check that unused fields 'union bpf_attr' are zero */
16999c55f7dSAlexei Starovoitov #define CHECK_ATTR(CMD) \
17099c55f7dSAlexei Starovoitov 	memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
17199c55f7dSAlexei Starovoitov 		   sizeof(attr->CMD##_LAST_FIELD), 0, \
17299c55f7dSAlexei Starovoitov 		   sizeof(*attr) - \
17399c55f7dSAlexei Starovoitov 		   offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
17499c55f7dSAlexei Starovoitov 		   sizeof(attr->CMD##_LAST_FIELD)) != NULL
17599c55f7dSAlexei Starovoitov 
1766c905981SAlexei Starovoitov #define BPF_MAP_CREATE_LAST_FIELD map_flags
17799c55f7dSAlexei Starovoitov /* called via syscall */
17899c55f7dSAlexei Starovoitov static int map_create(union bpf_attr *attr)
17999c55f7dSAlexei Starovoitov {
18099c55f7dSAlexei Starovoitov 	struct bpf_map *map;
18199c55f7dSAlexei Starovoitov 	int err;
18299c55f7dSAlexei Starovoitov 
18399c55f7dSAlexei Starovoitov 	err = CHECK_ATTR(BPF_MAP_CREATE);
18499c55f7dSAlexei Starovoitov 	if (err)
18599c55f7dSAlexei Starovoitov 		return -EINVAL;
18699c55f7dSAlexei Starovoitov 
18799c55f7dSAlexei Starovoitov 	/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
18899c55f7dSAlexei Starovoitov 	map = find_and_alloc_map(attr);
18999c55f7dSAlexei Starovoitov 	if (IS_ERR(map))
19099c55f7dSAlexei Starovoitov 		return PTR_ERR(map);
19199c55f7dSAlexei Starovoitov 
19299c55f7dSAlexei Starovoitov 	atomic_set(&map->refcnt, 1);
193c9da161cSDaniel Borkmann 	atomic_set(&map->usercnt, 1);
19499c55f7dSAlexei Starovoitov 
195aaac3ba9SAlexei Starovoitov 	err = bpf_map_charge_memlock(map);
196aaac3ba9SAlexei Starovoitov 	if (err)
197aaac3ba9SAlexei Starovoitov 		goto free_map;
198aaac3ba9SAlexei Starovoitov 
199aa79781bSDaniel Borkmann 	err = bpf_map_new_fd(map);
20099c55f7dSAlexei Starovoitov 	if (err < 0)
20199c55f7dSAlexei Starovoitov 		/* failed to allocate fd */
20299c55f7dSAlexei Starovoitov 		goto free_map;
20399c55f7dSAlexei Starovoitov 
20499c55f7dSAlexei Starovoitov 	return err;
20599c55f7dSAlexei Starovoitov 
20699c55f7dSAlexei Starovoitov free_map:
20799c55f7dSAlexei Starovoitov 	map->ops->map_free(map);
20899c55f7dSAlexei Starovoitov 	return err;
20999c55f7dSAlexei Starovoitov }
21099c55f7dSAlexei Starovoitov 
211db20fd2bSAlexei Starovoitov /* if error is returned, fd is released.
212db20fd2bSAlexei Starovoitov  * On success caller should complete fd access with matching fdput()
213db20fd2bSAlexei Starovoitov  */
214c2101297SDaniel Borkmann struct bpf_map *__bpf_map_get(struct fd f)
215db20fd2bSAlexei Starovoitov {
216db20fd2bSAlexei Starovoitov 	if (!f.file)
217db20fd2bSAlexei Starovoitov 		return ERR_PTR(-EBADF);
218db20fd2bSAlexei Starovoitov 	if (f.file->f_op != &bpf_map_fops) {
219db20fd2bSAlexei Starovoitov 		fdput(f);
220db20fd2bSAlexei Starovoitov 		return ERR_PTR(-EINVAL);
221db20fd2bSAlexei Starovoitov 	}
222db20fd2bSAlexei Starovoitov 
223c2101297SDaniel Borkmann 	return f.file->private_data;
224c2101297SDaniel Borkmann }
225c2101297SDaniel Borkmann 
22692117d84SAlexei Starovoitov /* prog's and map's refcnt limit */
22792117d84SAlexei Starovoitov #define BPF_MAX_REFCNT 32768
22892117d84SAlexei Starovoitov 
22992117d84SAlexei Starovoitov struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
230c9da161cSDaniel Borkmann {
23192117d84SAlexei Starovoitov 	if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
23292117d84SAlexei Starovoitov 		atomic_dec(&map->refcnt);
23392117d84SAlexei Starovoitov 		return ERR_PTR(-EBUSY);
23492117d84SAlexei Starovoitov 	}
235c9da161cSDaniel Borkmann 	if (uref)
236c9da161cSDaniel Borkmann 		atomic_inc(&map->usercnt);
23792117d84SAlexei Starovoitov 	return map;
238c9da161cSDaniel Borkmann }
239c9da161cSDaniel Borkmann 
240c9da161cSDaniel Borkmann struct bpf_map *bpf_map_get_with_uref(u32 ufd)
241c2101297SDaniel Borkmann {
242c2101297SDaniel Borkmann 	struct fd f = fdget(ufd);
243c2101297SDaniel Borkmann 	struct bpf_map *map;
244c2101297SDaniel Borkmann 
245c2101297SDaniel Borkmann 	map = __bpf_map_get(f);
246c2101297SDaniel Borkmann 	if (IS_ERR(map))
247c2101297SDaniel Borkmann 		return map;
248c2101297SDaniel Borkmann 
24992117d84SAlexei Starovoitov 	map = bpf_map_inc(map, true);
250c2101297SDaniel Borkmann 	fdput(f);
251db20fd2bSAlexei Starovoitov 
252db20fd2bSAlexei Starovoitov 	return map;
253db20fd2bSAlexei Starovoitov }
254db20fd2bSAlexei Starovoitov 
255db20fd2bSAlexei Starovoitov /* helper to convert user pointers passed inside __aligned_u64 fields */
256db20fd2bSAlexei Starovoitov static void __user *u64_to_ptr(__u64 val)
257db20fd2bSAlexei Starovoitov {
258db20fd2bSAlexei Starovoitov 	return (void __user *) (unsigned long) val;
259db20fd2bSAlexei Starovoitov }
260db20fd2bSAlexei Starovoitov 
261b8cdc051SAlexei Starovoitov int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
262b8cdc051SAlexei Starovoitov {
263b8cdc051SAlexei Starovoitov 	return -ENOTSUPP;
264b8cdc051SAlexei Starovoitov }
265b8cdc051SAlexei Starovoitov 
266db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
267db20fd2bSAlexei Starovoitov #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
268db20fd2bSAlexei Starovoitov 
269db20fd2bSAlexei Starovoitov static int map_lookup_elem(union bpf_attr *attr)
270db20fd2bSAlexei Starovoitov {
271db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
272db20fd2bSAlexei Starovoitov 	void __user *uvalue = u64_to_ptr(attr->value);
273db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
274db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
2758ebe667cSAlexei Starovoitov 	void *key, *value, *ptr;
27615a07b33SAlexei Starovoitov 	u32 value_size;
277592867bfSDaniel Borkmann 	struct fd f;
278db20fd2bSAlexei Starovoitov 	int err;
279db20fd2bSAlexei Starovoitov 
280db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
281db20fd2bSAlexei Starovoitov 		return -EINVAL;
282db20fd2bSAlexei Starovoitov 
283592867bfSDaniel Borkmann 	f = fdget(ufd);
284c2101297SDaniel Borkmann 	map = __bpf_map_get(f);
285db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
286db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
287db20fd2bSAlexei Starovoitov 
288db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
289db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
290db20fd2bSAlexei Starovoitov 	if (!key)
291db20fd2bSAlexei Starovoitov 		goto err_put;
292db20fd2bSAlexei Starovoitov 
293db20fd2bSAlexei Starovoitov 	err = -EFAULT;
294db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
295db20fd2bSAlexei Starovoitov 		goto free_key;
296db20fd2bSAlexei Starovoitov 
29715a07b33SAlexei Starovoitov 	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
29815a07b33SAlexei Starovoitov 	    map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
29915a07b33SAlexei Starovoitov 		value_size = round_up(map->value_size, 8) * num_possible_cpus();
30015a07b33SAlexei Starovoitov 	else
30115a07b33SAlexei Starovoitov 		value_size = map->value_size;
30215a07b33SAlexei Starovoitov 
3038ebe667cSAlexei Starovoitov 	err = -ENOMEM;
30415a07b33SAlexei Starovoitov 	value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
305db20fd2bSAlexei Starovoitov 	if (!value)
3068ebe667cSAlexei Starovoitov 		goto free_key;
3078ebe667cSAlexei Starovoitov 
30815a07b33SAlexei Starovoitov 	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
30915a07b33SAlexei Starovoitov 		err = bpf_percpu_hash_copy(map, key, value);
31015a07b33SAlexei Starovoitov 	} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
31115a07b33SAlexei Starovoitov 		err = bpf_percpu_array_copy(map, key, value);
312557c0c6eSAlexei Starovoitov 	} else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
313557c0c6eSAlexei Starovoitov 		err = bpf_stackmap_copy(map, key, value);
31415a07b33SAlexei Starovoitov 	} else {
3158ebe667cSAlexei Starovoitov 		rcu_read_lock();
3168ebe667cSAlexei Starovoitov 		ptr = map->ops->map_lookup_elem(map, key);
3178ebe667cSAlexei Starovoitov 		if (ptr)
31815a07b33SAlexei Starovoitov 			memcpy(value, ptr, value_size);
3198ebe667cSAlexei Starovoitov 		rcu_read_unlock();
32015a07b33SAlexei Starovoitov 		err = ptr ? 0 : -ENOENT;
32115a07b33SAlexei Starovoitov 	}
3228ebe667cSAlexei Starovoitov 
32315a07b33SAlexei Starovoitov 	if (err)
3248ebe667cSAlexei Starovoitov 		goto free_value;
325db20fd2bSAlexei Starovoitov 
326db20fd2bSAlexei Starovoitov 	err = -EFAULT;
32715a07b33SAlexei Starovoitov 	if (copy_to_user(uvalue, value, value_size) != 0)
3288ebe667cSAlexei Starovoitov 		goto free_value;
329db20fd2bSAlexei Starovoitov 
330db20fd2bSAlexei Starovoitov 	err = 0;
331db20fd2bSAlexei Starovoitov 
3328ebe667cSAlexei Starovoitov free_value:
3338ebe667cSAlexei Starovoitov 	kfree(value);
334db20fd2bSAlexei Starovoitov free_key:
335db20fd2bSAlexei Starovoitov 	kfree(key);
336db20fd2bSAlexei Starovoitov err_put:
337db20fd2bSAlexei Starovoitov 	fdput(f);
338db20fd2bSAlexei Starovoitov 	return err;
339db20fd2bSAlexei Starovoitov }
340db20fd2bSAlexei Starovoitov 
3413274f520SAlexei Starovoitov #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
342db20fd2bSAlexei Starovoitov 
343db20fd2bSAlexei Starovoitov static int map_update_elem(union bpf_attr *attr)
344db20fd2bSAlexei Starovoitov {
345db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
346db20fd2bSAlexei Starovoitov 	void __user *uvalue = u64_to_ptr(attr->value);
347db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
348db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
349db20fd2bSAlexei Starovoitov 	void *key, *value;
35015a07b33SAlexei Starovoitov 	u32 value_size;
351592867bfSDaniel Borkmann 	struct fd f;
352db20fd2bSAlexei Starovoitov 	int err;
353db20fd2bSAlexei Starovoitov 
354db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
355db20fd2bSAlexei Starovoitov 		return -EINVAL;
356db20fd2bSAlexei Starovoitov 
357592867bfSDaniel Borkmann 	f = fdget(ufd);
358c2101297SDaniel Borkmann 	map = __bpf_map_get(f);
359db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
360db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
361db20fd2bSAlexei Starovoitov 
362db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
363db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
364db20fd2bSAlexei Starovoitov 	if (!key)
365db20fd2bSAlexei Starovoitov 		goto err_put;
366db20fd2bSAlexei Starovoitov 
367db20fd2bSAlexei Starovoitov 	err = -EFAULT;
368db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
369db20fd2bSAlexei Starovoitov 		goto free_key;
370db20fd2bSAlexei Starovoitov 
37115a07b33SAlexei Starovoitov 	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
37215a07b33SAlexei Starovoitov 	    map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
37315a07b33SAlexei Starovoitov 		value_size = round_up(map->value_size, 8) * num_possible_cpus();
37415a07b33SAlexei Starovoitov 	else
37515a07b33SAlexei Starovoitov 		value_size = map->value_size;
37615a07b33SAlexei Starovoitov 
377db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
37815a07b33SAlexei Starovoitov 	value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
379db20fd2bSAlexei Starovoitov 	if (!value)
380db20fd2bSAlexei Starovoitov 		goto free_key;
381db20fd2bSAlexei Starovoitov 
382db20fd2bSAlexei Starovoitov 	err = -EFAULT;
38315a07b33SAlexei Starovoitov 	if (copy_from_user(value, uvalue, value_size) != 0)
384db20fd2bSAlexei Starovoitov 		goto free_value;
385db20fd2bSAlexei Starovoitov 
386b121d1e7SAlexei Starovoitov 	/* must increment bpf_prog_active to avoid kprobe+bpf triggering from
387b121d1e7SAlexei Starovoitov 	 * inside bpf map update or delete otherwise deadlocks are possible
388b121d1e7SAlexei Starovoitov 	 */
389b121d1e7SAlexei Starovoitov 	preempt_disable();
390b121d1e7SAlexei Starovoitov 	__this_cpu_inc(bpf_prog_active);
39115a07b33SAlexei Starovoitov 	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
39215a07b33SAlexei Starovoitov 		err = bpf_percpu_hash_update(map, key, value, attr->flags);
39315a07b33SAlexei Starovoitov 	} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
39415a07b33SAlexei Starovoitov 		err = bpf_percpu_array_update(map, key, value, attr->flags);
395*d056a788SDaniel Borkmann 	} else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
396*d056a788SDaniel Borkmann 		   map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
397*d056a788SDaniel Borkmann 		rcu_read_lock();
398*d056a788SDaniel Borkmann 		err = bpf_fd_array_map_update_elem(map, f.file, key, value,
399*d056a788SDaniel Borkmann 						   attr->flags);
400*d056a788SDaniel Borkmann 		rcu_read_unlock();
40115a07b33SAlexei Starovoitov 	} else {
402db20fd2bSAlexei Starovoitov 		rcu_read_lock();
4033274f520SAlexei Starovoitov 		err = map->ops->map_update_elem(map, key, value, attr->flags);
404db20fd2bSAlexei Starovoitov 		rcu_read_unlock();
40515a07b33SAlexei Starovoitov 	}
406b121d1e7SAlexei Starovoitov 	__this_cpu_dec(bpf_prog_active);
407b121d1e7SAlexei Starovoitov 	preempt_enable();
408db20fd2bSAlexei Starovoitov 
409db20fd2bSAlexei Starovoitov free_value:
410db20fd2bSAlexei Starovoitov 	kfree(value);
411db20fd2bSAlexei Starovoitov free_key:
412db20fd2bSAlexei Starovoitov 	kfree(key);
413db20fd2bSAlexei Starovoitov err_put:
414db20fd2bSAlexei Starovoitov 	fdput(f);
415db20fd2bSAlexei Starovoitov 	return err;
416db20fd2bSAlexei Starovoitov }
417db20fd2bSAlexei Starovoitov 
418db20fd2bSAlexei Starovoitov #define BPF_MAP_DELETE_ELEM_LAST_FIELD key
419db20fd2bSAlexei Starovoitov 
420db20fd2bSAlexei Starovoitov static int map_delete_elem(union bpf_attr *attr)
421db20fd2bSAlexei Starovoitov {
422db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
423db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
424db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
425592867bfSDaniel Borkmann 	struct fd f;
426db20fd2bSAlexei Starovoitov 	void *key;
427db20fd2bSAlexei Starovoitov 	int err;
428db20fd2bSAlexei Starovoitov 
429db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
430db20fd2bSAlexei Starovoitov 		return -EINVAL;
431db20fd2bSAlexei Starovoitov 
432592867bfSDaniel Borkmann 	f = fdget(ufd);
433c2101297SDaniel Borkmann 	map = __bpf_map_get(f);
434db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
435db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
436db20fd2bSAlexei Starovoitov 
437db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
438db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
439db20fd2bSAlexei Starovoitov 	if (!key)
440db20fd2bSAlexei Starovoitov 		goto err_put;
441db20fd2bSAlexei Starovoitov 
442db20fd2bSAlexei Starovoitov 	err = -EFAULT;
443db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
444db20fd2bSAlexei Starovoitov 		goto free_key;
445db20fd2bSAlexei Starovoitov 
446b121d1e7SAlexei Starovoitov 	preempt_disable();
447b121d1e7SAlexei Starovoitov 	__this_cpu_inc(bpf_prog_active);
448db20fd2bSAlexei Starovoitov 	rcu_read_lock();
449db20fd2bSAlexei Starovoitov 	err = map->ops->map_delete_elem(map, key);
450db20fd2bSAlexei Starovoitov 	rcu_read_unlock();
451b121d1e7SAlexei Starovoitov 	__this_cpu_dec(bpf_prog_active);
452b121d1e7SAlexei Starovoitov 	preempt_enable();
453db20fd2bSAlexei Starovoitov 
454db20fd2bSAlexei Starovoitov free_key:
455db20fd2bSAlexei Starovoitov 	kfree(key);
456db20fd2bSAlexei Starovoitov err_put:
457db20fd2bSAlexei Starovoitov 	fdput(f);
458db20fd2bSAlexei Starovoitov 	return err;
459db20fd2bSAlexei Starovoitov }
460db20fd2bSAlexei Starovoitov 
461db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
462db20fd2bSAlexei Starovoitov #define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
463db20fd2bSAlexei Starovoitov 
464db20fd2bSAlexei Starovoitov static int map_get_next_key(union bpf_attr *attr)
465db20fd2bSAlexei Starovoitov {
466db20fd2bSAlexei Starovoitov 	void __user *ukey = u64_to_ptr(attr->key);
467db20fd2bSAlexei Starovoitov 	void __user *unext_key = u64_to_ptr(attr->next_key);
468db20fd2bSAlexei Starovoitov 	int ufd = attr->map_fd;
469db20fd2bSAlexei Starovoitov 	struct bpf_map *map;
470db20fd2bSAlexei Starovoitov 	void *key, *next_key;
471592867bfSDaniel Borkmann 	struct fd f;
472db20fd2bSAlexei Starovoitov 	int err;
473db20fd2bSAlexei Starovoitov 
474db20fd2bSAlexei Starovoitov 	if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
475db20fd2bSAlexei Starovoitov 		return -EINVAL;
476db20fd2bSAlexei Starovoitov 
477592867bfSDaniel Borkmann 	f = fdget(ufd);
478c2101297SDaniel Borkmann 	map = __bpf_map_get(f);
479db20fd2bSAlexei Starovoitov 	if (IS_ERR(map))
480db20fd2bSAlexei Starovoitov 		return PTR_ERR(map);
481db20fd2bSAlexei Starovoitov 
482db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
483db20fd2bSAlexei Starovoitov 	key = kmalloc(map->key_size, GFP_USER);
484db20fd2bSAlexei Starovoitov 	if (!key)
485db20fd2bSAlexei Starovoitov 		goto err_put;
486db20fd2bSAlexei Starovoitov 
487db20fd2bSAlexei Starovoitov 	err = -EFAULT;
488db20fd2bSAlexei Starovoitov 	if (copy_from_user(key, ukey, map->key_size) != 0)
489db20fd2bSAlexei Starovoitov 		goto free_key;
490db20fd2bSAlexei Starovoitov 
491db20fd2bSAlexei Starovoitov 	err = -ENOMEM;
492db20fd2bSAlexei Starovoitov 	next_key = kmalloc(map->key_size, GFP_USER);
493db20fd2bSAlexei Starovoitov 	if (!next_key)
494db20fd2bSAlexei Starovoitov 		goto free_key;
495db20fd2bSAlexei Starovoitov 
496db20fd2bSAlexei Starovoitov 	rcu_read_lock();
497db20fd2bSAlexei Starovoitov 	err = map->ops->map_get_next_key(map, key, next_key);
498db20fd2bSAlexei Starovoitov 	rcu_read_unlock();
499db20fd2bSAlexei Starovoitov 	if (err)
500db20fd2bSAlexei Starovoitov 		goto free_next_key;
501db20fd2bSAlexei Starovoitov 
502db20fd2bSAlexei Starovoitov 	err = -EFAULT;
503db20fd2bSAlexei Starovoitov 	if (copy_to_user(unext_key, next_key, map->key_size) != 0)
504db20fd2bSAlexei Starovoitov 		goto free_next_key;
505db20fd2bSAlexei Starovoitov 
506db20fd2bSAlexei Starovoitov 	err = 0;
507db20fd2bSAlexei Starovoitov 
508db20fd2bSAlexei Starovoitov free_next_key:
509db20fd2bSAlexei Starovoitov 	kfree(next_key);
510db20fd2bSAlexei Starovoitov free_key:
511db20fd2bSAlexei Starovoitov 	kfree(key);
512db20fd2bSAlexei Starovoitov err_put:
513db20fd2bSAlexei Starovoitov 	fdput(f);
514db20fd2bSAlexei Starovoitov 	return err;
515db20fd2bSAlexei Starovoitov }
516db20fd2bSAlexei Starovoitov 
51709756af4SAlexei Starovoitov static LIST_HEAD(bpf_prog_types);
51809756af4SAlexei Starovoitov 
51909756af4SAlexei Starovoitov static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
52009756af4SAlexei Starovoitov {
52109756af4SAlexei Starovoitov 	struct bpf_prog_type_list *tl;
52209756af4SAlexei Starovoitov 
52309756af4SAlexei Starovoitov 	list_for_each_entry(tl, &bpf_prog_types, list_node) {
52409756af4SAlexei Starovoitov 		if (tl->type == type) {
52509756af4SAlexei Starovoitov 			prog->aux->ops = tl->ops;
52624701eceSDaniel Borkmann 			prog->type = type;
52709756af4SAlexei Starovoitov 			return 0;
52809756af4SAlexei Starovoitov 		}
52909756af4SAlexei Starovoitov 	}
53024701eceSDaniel Borkmann 
53109756af4SAlexei Starovoitov 	return -EINVAL;
53209756af4SAlexei Starovoitov }
53309756af4SAlexei Starovoitov 
53409756af4SAlexei Starovoitov void bpf_register_prog_type(struct bpf_prog_type_list *tl)
53509756af4SAlexei Starovoitov {
53609756af4SAlexei Starovoitov 	list_add(&tl->list_node, &bpf_prog_types);
53709756af4SAlexei Starovoitov }
53809756af4SAlexei Starovoitov 
5390a542a86SAlexei Starovoitov /* fixup insn->imm field of bpf_call instructions:
5400a542a86SAlexei Starovoitov  * if (insn->imm == BPF_FUNC_map_lookup_elem)
5410a542a86SAlexei Starovoitov  *      insn->imm = bpf_map_lookup_elem - __bpf_call_base;
5420a542a86SAlexei Starovoitov  * else if (insn->imm == BPF_FUNC_map_update_elem)
5430a542a86SAlexei Starovoitov  *      insn->imm = bpf_map_update_elem - __bpf_call_base;
5440a542a86SAlexei Starovoitov  * else ...
5450a542a86SAlexei Starovoitov  *
5460a542a86SAlexei Starovoitov  * this function is called after eBPF program passed verification
5470a542a86SAlexei Starovoitov  */
5480a542a86SAlexei Starovoitov static void fixup_bpf_calls(struct bpf_prog *prog)
5490a542a86SAlexei Starovoitov {
5500a542a86SAlexei Starovoitov 	const struct bpf_func_proto *fn;
5510a542a86SAlexei Starovoitov 	int i;
5520a542a86SAlexei Starovoitov 
5530a542a86SAlexei Starovoitov 	for (i = 0; i < prog->len; i++) {
5540a542a86SAlexei Starovoitov 		struct bpf_insn *insn = &prog->insnsi[i];
5550a542a86SAlexei Starovoitov 
5560a542a86SAlexei Starovoitov 		if (insn->code == (BPF_JMP | BPF_CALL)) {
5570a542a86SAlexei Starovoitov 			/* we reach here when program has bpf_call instructions
5580a542a86SAlexei Starovoitov 			 * and it passed bpf_check(), means that
5590a542a86SAlexei Starovoitov 			 * ops->get_func_proto must have been supplied, check it
5600a542a86SAlexei Starovoitov 			 */
5610a542a86SAlexei Starovoitov 			BUG_ON(!prog->aux->ops->get_func_proto);
5620a542a86SAlexei Starovoitov 
563c46646d0SDaniel Borkmann 			if (insn->imm == BPF_FUNC_get_route_realm)
564c46646d0SDaniel Borkmann 				prog->dst_needed = 1;
5653ad00405SDaniel Borkmann 			if (insn->imm == BPF_FUNC_get_prandom_u32)
5663ad00405SDaniel Borkmann 				bpf_user_rnd_init_once();
56704fd61abSAlexei Starovoitov 			if (insn->imm == BPF_FUNC_tail_call) {
56804fd61abSAlexei Starovoitov 				/* mark bpf_tail_call as different opcode
56904fd61abSAlexei Starovoitov 				 * to avoid conditional branch in
57004fd61abSAlexei Starovoitov 				 * interpeter for every normal call
57104fd61abSAlexei Starovoitov 				 * and to prevent accidental JITing by
57204fd61abSAlexei Starovoitov 				 * JIT compiler that doesn't support
57304fd61abSAlexei Starovoitov 				 * bpf_tail_call yet
57404fd61abSAlexei Starovoitov 				 */
57504fd61abSAlexei Starovoitov 				insn->imm = 0;
57604fd61abSAlexei Starovoitov 				insn->code |= BPF_X;
57704fd61abSAlexei Starovoitov 				continue;
57804fd61abSAlexei Starovoitov 			}
57904fd61abSAlexei Starovoitov 
5800a542a86SAlexei Starovoitov 			fn = prog->aux->ops->get_func_proto(insn->imm);
5810a542a86SAlexei Starovoitov 			/* all functions that have prototype and verifier allowed
5820a542a86SAlexei Starovoitov 			 * programs to call them, must be real in-kernel functions
5830a542a86SAlexei Starovoitov 			 */
5840a542a86SAlexei Starovoitov 			BUG_ON(!fn->func);
5850a542a86SAlexei Starovoitov 			insn->imm = fn->func - __bpf_call_base;
5860a542a86SAlexei Starovoitov 		}
5870a542a86SAlexei Starovoitov 	}
5880a542a86SAlexei Starovoitov }
5890a542a86SAlexei Starovoitov 
59009756af4SAlexei Starovoitov /* drop refcnt on maps used by eBPF program and free auxilary data */
59109756af4SAlexei Starovoitov static void free_used_maps(struct bpf_prog_aux *aux)
59209756af4SAlexei Starovoitov {
59309756af4SAlexei Starovoitov 	int i;
59409756af4SAlexei Starovoitov 
59509756af4SAlexei Starovoitov 	for (i = 0; i < aux->used_map_cnt; i++)
59609756af4SAlexei Starovoitov 		bpf_map_put(aux->used_maps[i]);
59709756af4SAlexei Starovoitov 
59809756af4SAlexei Starovoitov 	kfree(aux->used_maps);
59909756af4SAlexei Starovoitov }
60009756af4SAlexei Starovoitov 
601aaac3ba9SAlexei Starovoitov static int bpf_prog_charge_memlock(struct bpf_prog *prog)
602aaac3ba9SAlexei Starovoitov {
603aaac3ba9SAlexei Starovoitov 	struct user_struct *user = get_current_user();
604aaac3ba9SAlexei Starovoitov 	unsigned long memlock_limit;
605aaac3ba9SAlexei Starovoitov 
606aaac3ba9SAlexei Starovoitov 	memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
607aaac3ba9SAlexei Starovoitov 
608aaac3ba9SAlexei Starovoitov 	atomic_long_add(prog->pages, &user->locked_vm);
609aaac3ba9SAlexei Starovoitov 	if (atomic_long_read(&user->locked_vm) > memlock_limit) {
610aaac3ba9SAlexei Starovoitov 		atomic_long_sub(prog->pages, &user->locked_vm);
611aaac3ba9SAlexei Starovoitov 		free_uid(user);
612aaac3ba9SAlexei Starovoitov 		return -EPERM;
613aaac3ba9SAlexei Starovoitov 	}
614aaac3ba9SAlexei Starovoitov 	prog->aux->user = user;
615aaac3ba9SAlexei Starovoitov 	return 0;
616aaac3ba9SAlexei Starovoitov }
617aaac3ba9SAlexei Starovoitov 
618aaac3ba9SAlexei Starovoitov static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
619aaac3ba9SAlexei Starovoitov {
620aaac3ba9SAlexei Starovoitov 	struct user_struct *user = prog->aux->user;
621aaac3ba9SAlexei Starovoitov 
622aaac3ba9SAlexei Starovoitov 	atomic_long_sub(prog->pages, &user->locked_vm);
623aaac3ba9SAlexei Starovoitov 	free_uid(user);
624aaac3ba9SAlexei Starovoitov }
625aaac3ba9SAlexei Starovoitov 
626e9d8afa9SDaniel Borkmann static void __prog_put_common(struct rcu_head *rcu)
627abf2e7d6SAlexei Starovoitov {
628abf2e7d6SAlexei Starovoitov 	struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
629abf2e7d6SAlexei Starovoitov 
630abf2e7d6SAlexei Starovoitov 	free_used_maps(aux);
631aaac3ba9SAlexei Starovoitov 	bpf_prog_uncharge_memlock(aux->prog);
632abf2e7d6SAlexei Starovoitov 	bpf_prog_free(aux->prog);
633abf2e7d6SAlexei Starovoitov }
634abf2e7d6SAlexei Starovoitov 
635abf2e7d6SAlexei Starovoitov /* version of bpf_prog_put() that is called after a grace period */
636abf2e7d6SAlexei Starovoitov void bpf_prog_put_rcu(struct bpf_prog *prog)
637abf2e7d6SAlexei Starovoitov {
638e9d8afa9SDaniel Borkmann 	if (atomic_dec_and_test(&prog->aux->refcnt))
639e9d8afa9SDaniel Borkmann 		call_rcu(&prog->aux->rcu, __prog_put_common);
640abf2e7d6SAlexei Starovoitov }
641abf2e7d6SAlexei Starovoitov 
64209756af4SAlexei Starovoitov void bpf_prog_put(struct bpf_prog *prog)
64309756af4SAlexei Starovoitov {
644e9d8afa9SDaniel Borkmann 	if (atomic_dec_and_test(&prog->aux->refcnt))
645e9d8afa9SDaniel Borkmann 		__prog_put_common(&prog->aux->rcu);
64609756af4SAlexei Starovoitov }
647e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_put);
64809756af4SAlexei Starovoitov 
64909756af4SAlexei Starovoitov static int bpf_prog_release(struct inode *inode, struct file *filp)
65009756af4SAlexei Starovoitov {
65109756af4SAlexei Starovoitov 	struct bpf_prog *prog = filp->private_data;
65209756af4SAlexei Starovoitov 
653abf2e7d6SAlexei Starovoitov 	bpf_prog_put_rcu(prog);
65409756af4SAlexei Starovoitov 	return 0;
65509756af4SAlexei Starovoitov }
65609756af4SAlexei Starovoitov 
65709756af4SAlexei Starovoitov static const struct file_operations bpf_prog_fops = {
65809756af4SAlexei Starovoitov         .release = bpf_prog_release,
65909756af4SAlexei Starovoitov };
66009756af4SAlexei Starovoitov 
661b2197755SDaniel Borkmann int bpf_prog_new_fd(struct bpf_prog *prog)
662aa79781bSDaniel Borkmann {
663aa79781bSDaniel Borkmann 	return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
664aa79781bSDaniel Borkmann 				O_RDWR | O_CLOEXEC);
665aa79781bSDaniel Borkmann }
666aa79781bSDaniel Borkmann 
667c2101297SDaniel Borkmann static struct bpf_prog *__bpf_prog_get(struct fd f)
66809756af4SAlexei Starovoitov {
66909756af4SAlexei Starovoitov 	if (!f.file)
67009756af4SAlexei Starovoitov 		return ERR_PTR(-EBADF);
67109756af4SAlexei Starovoitov 	if (f.file->f_op != &bpf_prog_fops) {
67209756af4SAlexei Starovoitov 		fdput(f);
67309756af4SAlexei Starovoitov 		return ERR_PTR(-EINVAL);
67409756af4SAlexei Starovoitov 	}
67509756af4SAlexei Starovoitov 
676c2101297SDaniel Borkmann 	return f.file->private_data;
67709756af4SAlexei Starovoitov }
67809756af4SAlexei Starovoitov 
67992117d84SAlexei Starovoitov struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
68092117d84SAlexei Starovoitov {
68192117d84SAlexei Starovoitov 	if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
68292117d84SAlexei Starovoitov 		atomic_dec(&prog->aux->refcnt);
68392117d84SAlexei Starovoitov 		return ERR_PTR(-EBUSY);
68492117d84SAlexei Starovoitov 	}
68592117d84SAlexei Starovoitov 	return prog;
68692117d84SAlexei Starovoitov }
68792117d84SAlexei Starovoitov 
68809756af4SAlexei Starovoitov /* called by sockets/tracing/seccomp before attaching program to an event
68909756af4SAlexei Starovoitov  * pairs with bpf_prog_put()
69009756af4SAlexei Starovoitov  */
69109756af4SAlexei Starovoitov struct bpf_prog *bpf_prog_get(u32 ufd)
69209756af4SAlexei Starovoitov {
69309756af4SAlexei Starovoitov 	struct fd f = fdget(ufd);
69409756af4SAlexei Starovoitov 	struct bpf_prog *prog;
69509756af4SAlexei Starovoitov 
696c2101297SDaniel Borkmann 	prog = __bpf_prog_get(f);
69709756af4SAlexei Starovoitov 	if (IS_ERR(prog))
69809756af4SAlexei Starovoitov 		return prog;
69909756af4SAlexei Starovoitov 
70092117d84SAlexei Starovoitov 	prog = bpf_prog_inc(prog);
70109756af4SAlexei Starovoitov 	fdput(f);
702c2101297SDaniel Borkmann 
70309756af4SAlexei Starovoitov 	return prog;
70409756af4SAlexei Starovoitov }
705e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_get);
70609756af4SAlexei Starovoitov 
70709756af4SAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */
7082541517cSAlexei Starovoitov #define	BPF_PROG_LOAD_LAST_FIELD kern_version
70909756af4SAlexei Starovoitov 
71009756af4SAlexei Starovoitov static int bpf_prog_load(union bpf_attr *attr)
71109756af4SAlexei Starovoitov {
71209756af4SAlexei Starovoitov 	enum bpf_prog_type type = attr->prog_type;
71309756af4SAlexei Starovoitov 	struct bpf_prog *prog;
71409756af4SAlexei Starovoitov 	int err;
71509756af4SAlexei Starovoitov 	char license[128];
71609756af4SAlexei Starovoitov 	bool is_gpl;
71709756af4SAlexei Starovoitov 
71809756af4SAlexei Starovoitov 	if (CHECK_ATTR(BPF_PROG_LOAD))
71909756af4SAlexei Starovoitov 		return -EINVAL;
72009756af4SAlexei Starovoitov 
72109756af4SAlexei Starovoitov 	/* copy eBPF program license from user space */
72209756af4SAlexei Starovoitov 	if (strncpy_from_user(license, u64_to_ptr(attr->license),
72309756af4SAlexei Starovoitov 			      sizeof(license) - 1) < 0)
72409756af4SAlexei Starovoitov 		return -EFAULT;
72509756af4SAlexei Starovoitov 	license[sizeof(license) - 1] = 0;
72609756af4SAlexei Starovoitov 
72709756af4SAlexei Starovoitov 	/* eBPF programs must be GPL compatible to use GPL-ed functions */
72809756af4SAlexei Starovoitov 	is_gpl = license_is_gpl_compatible(license);
72909756af4SAlexei Starovoitov 
73009756af4SAlexei Starovoitov 	if (attr->insn_cnt >= BPF_MAXINSNS)
73109756af4SAlexei Starovoitov 		return -EINVAL;
73209756af4SAlexei Starovoitov 
7332541517cSAlexei Starovoitov 	if (type == BPF_PROG_TYPE_KPROBE &&
7342541517cSAlexei Starovoitov 	    attr->kern_version != LINUX_VERSION_CODE)
7352541517cSAlexei Starovoitov 		return -EINVAL;
7362541517cSAlexei Starovoitov 
7371be7f75dSAlexei Starovoitov 	if (type != BPF_PROG_TYPE_SOCKET_FILTER && !capable(CAP_SYS_ADMIN))
7381be7f75dSAlexei Starovoitov 		return -EPERM;
7391be7f75dSAlexei Starovoitov 
74009756af4SAlexei Starovoitov 	/* plain bpf_prog allocation */
74109756af4SAlexei Starovoitov 	prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
74209756af4SAlexei Starovoitov 	if (!prog)
74309756af4SAlexei Starovoitov 		return -ENOMEM;
74409756af4SAlexei Starovoitov 
745aaac3ba9SAlexei Starovoitov 	err = bpf_prog_charge_memlock(prog);
746aaac3ba9SAlexei Starovoitov 	if (err)
747aaac3ba9SAlexei Starovoitov 		goto free_prog_nouncharge;
748aaac3ba9SAlexei Starovoitov 
74909756af4SAlexei Starovoitov 	prog->len = attr->insn_cnt;
75009756af4SAlexei Starovoitov 
75109756af4SAlexei Starovoitov 	err = -EFAULT;
75209756af4SAlexei Starovoitov 	if (copy_from_user(prog->insns, u64_to_ptr(attr->insns),
75309756af4SAlexei Starovoitov 			   prog->len * sizeof(struct bpf_insn)) != 0)
75409756af4SAlexei Starovoitov 		goto free_prog;
75509756af4SAlexei Starovoitov 
75609756af4SAlexei Starovoitov 	prog->orig_prog = NULL;
757a91263d5SDaniel Borkmann 	prog->jited = 0;
75809756af4SAlexei Starovoitov 
75909756af4SAlexei Starovoitov 	atomic_set(&prog->aux->refcnt, 1);
760a91263d5SDaniel Borkmann 	prog->gpl_compatible = is_gpl ? 1 : 0;
76109756af4SAlexei Starovoitov 
76209756af4SAlexei Starovoitov 	/* find program type: socket_filter vs tracing_filter */
76309756af4SAlexei Starovoitov 	err = find_prog_type(type, prog);
76409756af4SAlexei Starovoitov 	if (err < 0)
76509756af4SAlexei Starovoitov 		goto free_prog;
76609756af4SAlexei Starovoitov 
76709756af4SAlexei Starovoitov 	/* run eBPF verifier */
7689bac3d6dSAlexei Starovoitov 	err = bpf_check(&prog, attr);
76909756af4SAlexei Starovoitov 	if (err < 0)
77009756af4SAlexei Starovoitov 		goto free_used_maps;
77109756af4SAlexei Starovoitov 
7720a542a86SAlexei Starovoitov 	/* fixup BPF_CALL->imm field */
7730a542a86SAlexei Starovoitov 	fixup_bpf_calls(prog);
7740a542a86SAlexei Starovoitov 
77509756af4SAlexei Starovoitov 	/* eBPF program is ready to be JITed */
776d1c55ab5SDaniel Borkmann 	prog = bpf_prog_select_runtime(prog, &err);
77704fd61abSAlexei Starovoitov 	if (err < 0)
77804fd61abSAlexei Starovoitov 		goto free_used_maps;
77909756af4SAlexei Starovoitov 
780aa79781bSDaniel Borkmann 	err = bpf_prog_new_fd(prog);
78109756af4SAlexei Starovoitov 	if (err < 0)
78209756af4SAlexei Starovoitov 		/* failed to allocate fd */
78309756af4SAlexei Starovoitov 		goto free_used_maps;
78409756af4SAlexei Starovoitov 
78509756af4SAlexei Starovoitov 	return err;
78609756af4SAlexei Starovoitov 
78709756af4SAlexei Starovoitov free_used_maps:
78809756af4SAlexei Starovoitov 	free_used_maps(prog->aux);
78909756af4SAlexei Starovoitov free_prog:
790aaac3ba9SAlexei Starovoitov 	bpf_prog_uncharge_memlock(prog);
791aaac3ba9SAlexei Starovoitov free_prog_nouncharge:
79209756af4SAlexei Starovoitov 	bpf_prog_free(prog);
79309756af4SAlexei Starovoitov 	return err;
79409756af4SAlexei Starovoitov }
79509756af4SAlexei Starovoitov 
796b2197755SDaniel Borkmann #define BPF_OBJ_LAST_FIELD bpf_fd
797b2197755SDaniel Borkmann 
798b2197755SDaniel Borkmann static int bpf_obj_pin(const union bpf_attr *attr)
799b2197755SDaniel Borkmann {
800b2197755SDaniel Borkmann 	if (CHECK_ATTR(BPF_OBJ))
801b2197755SDaniel Borkmann 		return -EINVAL;
802b2197755SDaniel Borkmann 
803b2197755SDaniel Borkmann 	return bpf_obj_pin_user(attr->bpf_fd, u64_to_ptr(attr->pathname));
804b2197755SDaniel Borkmann }
805b2197755SDaniel Borkmann 
806b2197755SDaniel Borkmann static int bpf_obj_get(const union bpf_attr *attr)
807b2197755SDaniel Borkmann {
808b2197755SDaniel Borkmann 	if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0)
809b2197755SDaniel Borkmann 		return -EINVAL;
810b2197755SDaniel Borkmann 
811b2197755SDaniel Borkmann 	return bpf_obj_get_user(u64_to_ptr(attr->pathname));
812b2197755SDaniel Borkmann }
813b2197755SDaniel Borkmann 
81499c55f7dSAlexei Starovoitov SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
81599c55f7dSAlexei Starovoitov {
81699c55f7dSAlexei Starovoitov 	union bpf_attr attr = {};
81799c55f7dSAlexei Starovoitov 	int err;
81899c55f7dSAlexei Starovoitov 
8191be7f75dSAlexei Starovoitov 	if (!capable(CAP_SYS_ADMIN) && sysctl_unprivileged_bpf_disabled)
82099c55f7dSAlexei Starovoitov 		return -EPERM;
82199c55f7dSAlexei Starovoitov 
82299c55f7dSAlexei Starovoitov 	if (!access_ok(VERIFY_READ, uattr, 1))
82399c55f7dSAlexei Starovoitov 		return -EFAULT;
82499c55f7dSAlexei Starovoitov 
82599c55f7dSAlexei Starovoitov 	if (size > PAGE_SIZE)	/* silly large */
82699c55f7dSAlexei Starovoitov 		return -E2BIG;
82799c55f7dSAlexei Starovoitov 
82899c55f7dSAlexei Starovoitov 	/* If we're handed a bigger struct than we know of,
82999c55f7dSAlexei Starovoitov 	 * ensure all the unknown bits are 0 - i.e. new
83099c55f7dSAlexei Starovoitov 	 * user-space does not rely on any kernel feature
83199c55f7dSAlexei Starovoitov 	 * extensions we dont know about yet.
83299c55f7dSAlexei Starovoitov 	 */
83399c55f7dSAlexei Starovoitov 	if (size > sizeof(attr)) {
83499c55f7dSAlexei Starovoitov 		unsigned char __user *addr;
83599c55f7dSAlexei Starovoitov 		unsigned char __user *end;
83699c55f7dSAlexei Starovoitov 		unsigned char val;
83799c55f7dSAlexei Starovoitov 
83899c55f7dSAlexei Starovoitov 		addr = (void __user *)uattr + sizeof(attr);
83999c55f7dSAlexei Starovoitov 		end  = (void __user *)uattr + size;
84099c55f7dSAlexei Starovoitov 
84199c55f7dSAlexei Starovoitov 		for (; addr < end; addr++) {
84299c55f7dSAlexei Starovoitov 			err = get_user(val, addr);
84399c55f7dSAlexei Starovoitov 			if (err)
84499c55f7dSAlexei Starovoitov 				return err;
84599c55f7dSAlexei Starovoitov 			if (val)
84699c55f7dSAlexei Starovoitov 				return -E2BIG;
84799c55f7dSAlexei Starovoitov 		}
84899c55f7dSAlexei Starovoitov 		size = sizeof(attr);
84999c55f7dSAlexei Starovoitov 	}
85099c55f7dSAlexei Starovoitov 
85199c55f7dSAlexei Starovoitov 	/* copy attributes from user space, may be less than sizeof(bpf_attr) */
85299c55f7dSAlexei Starovoitov 	if (copy_from_user(&attr, uattr, size) != 0)
85399c55f7dSAlexei Starovoitov 		return -EFAULT;
85499c55f7dSAlexei Starovoitov 
85599c55f7dSAlexei Starovoitov 	switch (cmd) {
85699c55f7dSAlexei Starovoitov 	case BPF_MAP_CREATE:
85799c55f7dSAlexei Starovoitov 		err = map_create(&attr);
85899c55f7dSAlexei Starovoitov 		break;
859db20fd2bSAlexei Starovoitov 	case BPF_MAP_LOOKUP_ELEM:
860db20fd2bSAlexei Starovoitov 		err = map_lookup_elem(&attr);
861db20fd2bSAlexei Starovoitov 		break;
862db20fd2bSAlexei Starovoitov 	case BPF_MAP_UPDATE_ELEM:
863db20fd2bSAlexei Starovoitov 		err = map_update_elem(&attr);
864db20fd2bSAlexei Starovoitov 		break;
865db20fd2bSAlexei Starovoitov 	case BPF_MAP_DELETE_ELEM:
866db20fd2bSAlexei Starovoitov 		err = map_delete_elem(&attr);
867db20fd2bSAlexei Starovoitov 		break;
868db20fd2bSAlexei Starovoitov 	case BPF_MAP_GET_NEXT_KEY:
869db20fd2bSAlexei Starovoitov 		err = map_get_next_key(&attr);
870db20fd2bSAlexei Starovoitov 		break;
87109756af4SAlexei Starovoitov 	case BPF_PROG_LOAD:
87209756af4SAlexei Starovoitov 		err = bpf_prog_load(&attr);
87309756af4SAlexei Starovoitov 		break;
874b2197755SDaniel Borkmann 	case BPF_OBJ_PIN:
875b2197755SDaniel Borkmann 		err = bpf_obj_pin(&attr);
876b2197755SDaniel Borkmann 		break;
877b2197755SDaniel Borkmann 	case BPF_OBJ_GET:
878b2197755SDaniel Borkmann 		err = bpf_obj_get(&attr);
879b2197755SDaniel Borkmann 		break;
88099c55f7dSAlexei Starovoitov 	default:
88199c55f7dSAlexei Starovoitov 		err = -EINVAL;
88299c55f7dSAlexei Starovoitov 		break;
88399c55f7dSAlexei Starovoitov 	}
88499c55f7dSAlexei Starovoitov 
88599c55f7dSAlexei Starovoitov 	return err;
88699c55f7dSAlexei Starovoitov }
887