blob: 4c3075b5d8403e9aea47ca9b4b3f5fab25617257 [file] [log] [blame]
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12#include <linux/bpf.h>
Daniel Borkmanna67edbf2017-01-25 02:28:18 +010013#include <linux/bpf_trace.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070014#include <linux/syscalls.h>
15#include <linux/slab.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010016#include <linux/sched/signal.h>
Daniel Borkmannd407bd22017-01-18 15:14:17 +010017#include <linux/vmalloc.h>
18#include <linux/mmzone.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070019#include <linux/anon_inodes.h>
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -070020#include <linux/file.h>
Alexei Starovoitov09756af2014-09-26 00:17:00 -070021#include <linux/license.h>
22#include <linux/filter.h>
Alexei Starovoitov25415172015-03-25 12:49:20 -070023#include <linux/version.h>
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +010024#include <linux/kernel.h>
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070025#include <linux/idr.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070026
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080027DEFINE_PER_CPU(int, bpf_prog_active);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070028static DEFINE_IDR(prog_idr);
29static DEFINE_SPINLOCK(prog_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -070030static DEFINE_IDR(map_idr);
31static DEFINE_SPINLOCK(map_idr_lock);
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080032
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070033int sysctl_unprivileged_bpf_disabled __read_mostly;
34
Johannes Berg40077e02017-04-11 15:34:58 +020035static const struct bpf_map_ops * const bpf_map_types[] = {
36#define BPF_PROG_TYPE(_id, _ops)
37#define BPF_MAP_TYPE(_id, _ops) \
38 [_id] = &_ops,
39#include <linux/bpf_types.h>
40#undef BPF_PROG_TYPE
41#undef BPF_MAP_TYPE
42};
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070043
44static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
45{
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070046 struct bpf_map *map;
47
Johannes Berg40077e02017-04-11 15:34:58 +020048 if (attr->map_type >= ARRAY_SIZE(bpf_map_types) ||
49 !bpf_map_types[attr->map_type])
50 return ERR_PTR(-EINVAL);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070051
Johannes Berg40077e02017-04-11 15:34:58 +020052 map = bpf_map_types[attr->map_type]->map_alloc(attr);
53 if (IS_ERR(map))
54 return map;
55 map->ops = bpf_map_types[attr->map_type];
56 map->map_type = attr->map_type;
57 return map;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070058}
59
Daniel Borkmannd407bd22017-01-18 15:14:17 +010060void *bpf_map_area_alloc(size_t size)
61{
62 /* We definitely need __GFP_NORETRY, so OOM killer doesn't
63 * trigger under memory pressure as we really just want to
64 * fail instead.
65 */
66 const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
67 void *area;
68
69 if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
70 area = kmalloc(size, GFP_USER | flags);
71 if (area != NULL)
72 return area;
73 }
74
Michal Hocko19809c22017-05-08 15:57:44 -070075 return __vmalloc(size, GFP_KERNEL | flags, PAGE_KERNEL);
Daniel Borkmannd407bd22017-01-18 15:14:17 +010076}
77
78void bpf_map_area_free(void *area)
79{
80 kvfree(area);
81}
82
Alexei Starovoitov6c905982016-03-07 21:57:15 -080083int bpf_map_precharge_memlock(u32 pages)
84{
85 struct user_struct *user = get_current_user();
86 unsigned long memlock_limit, cur;
87
88 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
89 cur = atomic_long_read(&user->locked_vm);
90 free_uid(user);
91 if (cur + pages > memlock_limit)
92 return -EPERM;
93 return 0;
94}
95
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -070096static int bpf_map_charge_memlock(struct bpf_map *map)
97{
98 struct user_struct *user = get_current_user();
99 unsigned long memlock_limit;
100
101 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
102
103 atomic_long_add(map->pages, &user->locked_vm);
104
105 if (atomic_long_read(&user->locked_vm) > memlock_limit) {
106 atomic_long_sub(map->pages, &user->locked_vm);
107 free_uid(user);
108 return -EPERM;
109 }
110 map->user = user;
111 return 0;
112}
113
114static void bpf_map_uncharge_memlock(struct bpf_map *map)
115{
116 struct user_struct *user = map->user;
117
118 atomic_long_sub(map->pages, &user->locked_vm);
119 free_uid(user);
120}
121
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700122static int bpf_map_alloc_id(struct bpf_map *map)
123{
124 int id;
125
126 spin_lock_bh(&map_idr_lock);
127 id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
128 if (id > 0)
129 map->id = id;
130 spin_unlock_bh(&map_idr_lock);
131
132 if (WARN_ON_ONCE(!id))
133 return -ENOSPC;
134
135 return id > 0 ? 0 : id;
136}
137
138static void bpf_map_free_id(struct bpf_map *map)
139{
140 spin_lock_bh(&map_idr_lock);
141 idr_remove(&map_idr, map->id);
142 spin_unlock_bh(&map_idr_lock);
143}
144
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700145/* called from workqueue */
146static void bpf_map_free_deferred(struct work_struct *work)
147{
148 struct bpf_map *map = container_of(work, struct bpf_map, work);
149
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700150 bpf_map_uncharge_memlock(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700151 /* implementation dependent freeing */
152 map->ops->map_free(map);
153}
154
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100155static void bpf_map_put_uref(struct bpf_map *map)
156{
157 if (atomic_dec_and_test(&map->usercnt)) {
158 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
159 bpf_fd_array_map_clear(map);
160 }
161}
162
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700163/* decrement map refcnt and schedule it for freeing via workqueue
164 * (unrelying map implementation ops->map_free() might sleep)
165 */
166void bpf_map_put(struct bpf_map *map)
167{
168 if (atomic_dec_and_test(&map->refcnt)) {
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700169 bpf_map_free_id(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700170 INIT_WORK(&map->work, bpf_map_free_deferred);
171 schedule_work(&map->work);
172 }
173}
174
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100175void bpf_map_put_with_uref(struct bpf_map *map)
176{
177 bpf_map_put_uref(map);
178 bpf_map_put(map);
179}
180
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700181static int bpf_map_release(struct inode *inode, struct file *filp)
182{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200183 struct bpf_map *map = filp->private_data;
184
185 if (map->ops->map_release)
186 map->ops->map_release(map, filp);
187
188 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700189 return 0;
190}
191
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100192#ifdef CONFIG_PROC_FS
193static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
194{
195 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100196 const struct bpf_array *array;
197 u32 owner_prog_type = 0;
198
199 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
200 array = container_of(map, struct bpf_array, map);
201 owner_prog_type = array->owner_prog_type;
202 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100203
204 seq_printf(m,
205 "map_type:\t%u\n"
206 "key_size:\t%u\n"
207 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100208 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100209 "map_flags:\t%#x\n"
210 "memlock:\t%llu\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100211 map->map_type,
212 map->key_size,
213 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100214 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100215 map->map_flags,
216 map->pages * 1ULL << PAGE_SHIFT);
217
218 if (owner_prog_type)
219 seq_printf(m, "owner_prog_type:\t%u\n",
220 owner_prog_type);
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100221}
222#endif
223
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700224static const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100225#ifdef CONFIG_PROC_FS
226 .show_fdinfo = bpf_map_show_fdinfo,
227#endif
228 .release = bpf_map_release,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700229};
230
Daniel Borkmannb2197752015-10-29 14:58:09 +0100231int bpf_map_new_fd(struct bpf_map *map)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100232{
233 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
234 O_RDWR | O_CLOEXEC);
235}
236
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700237/* helper macro to check that unused fields 'union bpf_attr' are zero */
238#define CHECK_ATTR(CMD) \
239 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
240 sizeof(attr->CMD##_LAST_FIELD), 0, \
241 sizeof(*attr) - \
242 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
243 sizeof(attr->CMD##_LAST_FIELD)) != NULL
244
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700245#define BPF_MAP_CREATE_LAST_FIELD inner_map_fd
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700246/* called via syscall */
247static int map_create(union bpf_attr *attr)
248{
249 struct bpf_map *map;
250 int err;
251
252 err = CHECK_ATTR(BPF_MAP_CREATE);
253 if (err)
254 return -EINVAL;
255
256 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
257 map = find_and_alloc_map(attr);
258 if (IS_ERR(map))
259 return PTR_ERR(map);
260
261 atomic_set(&map->refcnt, 1);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100262 atomic_set(&map->usercnt, 1);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700263
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700264 err = bpf_map_charge_memlock(map);
265 if (err)
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100266 goto free_map_nouncharge;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700267
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700268 err = bpf_map_alloc_id(map);
269 if (err)
270 goto free_map;
271
Daniel Borkmannaa797812015-10-29 14:58:06 +0100272 err = bpf_map_new_fd(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700273 if (err < 0)
274 /* failed to allocate fd */
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700275 goto free_id;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700276
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100277 trace_bpf_map_create(map, err);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700278 return err;
279
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700280free_id:
281 bpf_map_free_id(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700282free_map:
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100283 bpf_map_uncharge_memlock(map);
284free_map_nouncharge:
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700285 map->ops->map_free(map);
286 return err;
287}
288
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700289/* if error is returned, fd is released.
290 * On success caller should complete fd access with matching fdput()
291 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100292struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700293{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700294 if (!f.file)
295 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700296 if (f.file->f_op != &bpf_map_fops) {
297 fdput(f);
298 return ERR_PTR(-EINVAL);
299 }
300
Daniel Borkmannc2101292015-10-29 14:58:07 +0100301 return f.file->private_data;
302}
303
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700304/* prog's and map's refcnt limit */
305#define BPF_MAX_REFCNT 32768
306
307struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100308{
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700309 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
310 atomic_dec(&map->refcnt);
311 return ERR_PTR(-EBUSY);
312 }
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100313 if (uref)
314 atomic_inc(&map->usercnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700315 return map;
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100316}
317
318struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100319{
320 struct fd f = fdget(ufd);
321 struct bpf_map *map;
322
323 map = __bpf_map_get(f);
324 if (IS_ERR(map))
325 return map;
326
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700327 map = bpf_map_inc(map, true);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100328 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700329
330 return map;
331}
332
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -0800333int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
334{
335 return -ENOTSUPP;
336}
337
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700338/* last field in 'union bpf_attr' used by this command */
339#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
340
341static int map_lookup_elem(union bpf_attr *attr)
342{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100343 void __user *ukey = u64_to_user_ptr(attr->key);
344 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700345 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700346 struct bpf_map *map;
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800347 void *key, *value, *ptr;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800348 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200349 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700350 int err;
351
352 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
353 return -EINVAL;
354
Daniel Borkmann592867b2015-09-08 18:00:09 +0200355 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100356 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700357 if (IS_ERR(map))
358 return PTR_ERR(map);
359
360 err = -ENOMEM;
361 key = kmalloc(map->key_size, GFP_USER);
362 if (!key)
363 goto err_put;
364
365 err = -EFAULT;
366 if (copy_from_user(key, ukey, map->key_size) != 0)
367 goto free_key;
368
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800369 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800370 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800371 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
372 value_size = round_up(map->value_size, 8) * num_possible_cpus();
373 else
374 value_size = map->value_size;
375
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800376 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800377 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700378 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800379 goto free_key;
380
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800381 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
382 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800383 err = bpf_percpu_hash_copy(map, key, value);
384 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
385 err = bpf_percpu_array_copy(map, key, value);
Alexei Starovoitov557c0c62016-03-07 21:57:17 -0800386 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
387 err = bpf_stackmap_copy(map, key, value);
Martin KaFai Laubcc6b1b2017-03-22 10:00:34 -0700388 } else if (map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
389 map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700390 err = -ENOTSUPP;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800391 } else {
392 rcu_read_lock();
393 ptr = map->ops->map_lookup_elem(map, key);
394 if (ptr)
395 memcpy(value, ptr, value_size);
396 rcu_read_unlock();
397 err = ptr ? 0 : -ENOENT;
398 }
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800399
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800400 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800401 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700402
403 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800404 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800405 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700406
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100407 trace_bpf_map_lookup_elem(map, ufd, key, value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700408 err = 0;
409
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800410free_value:
411 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700412free_key:
413 kfree(key);
414err_put:
415 fdput(f);
416 return err;
417}
418
Alexei Starovoitov3274f522014-11-13 17:36:44 -0800419#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700420
421static int map_update_elem(union bpf_attr *attr)
422{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100423 void __user *ukey = u64_to_user_ptr(attr->key);
424 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700425 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700426 struct bpf_map *map;
427 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800428 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200429 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700430 int err;
431
432 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
433 return -EINVAL;
434
Daniel Borkmann592867b2015-09-08 18:00:09 +0200435 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100436 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700437 if (IS_ERR(map))
438 return PTR_ERR(map);
439
440 err = -ENOMEM;
441 key = kmalloc(map->key_size, GFP_USER);
442 if (!key)
443 goto err_put;
444
445 err = -EFAULT;
446 if (copy_from_user(key, ukey, map->key_size) != 0)
447 goto free_key;
448
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800449 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800450 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800451 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
452 value_size = round_up(map->value_size, 8) * num_possible_cpus();
453 else
454 value_size = map->value_size;
455
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700456 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800457 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700458 if (!value)
459 goto free_key;
460
461 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800462 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700463 goto free_value;
464
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800465 /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
466 * inside bpf map update or delete otherwise deadlocks are possible
467 */
468 preempt_disable();
469 __this_cpu_inc(bpf_prog_active);
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800470 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
471 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800472 err = bpf_percpu_hash_update(map, key, value, attr->flags);
473 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
474 err = bpf_percpu_array_update(map, key, value, attr->flags);
Daniel Borkmannd056a782016-06-15 22:47:13 +0200475 } else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
Martin KaFai Lau4ed8ec52016-06-30 10:28:43 -0700476 map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700477 map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY ||
478 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS) {
Daniel Borkmannd056a782016-06-15 22:47:13 +0200479 rcu_read_lock();
480 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
481 attr->flags);
482 rcu_read_unlock();
Martin KaFai Laubcc6b1b2017-03-22 10:00:34 -0700483 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
484 rcu_read_lock();
485 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
486 attr->flags);
487 rcu_read_unlock();
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800488 } else {
489 rcu_read_lock();
490 err = map->ops->map_update_elem(map, key, value, attr->flags);
491 rcu_read_unlock();
492 }
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800493 __this_cpu_dec(bpf_prog_active);
494 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700495
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100496 if (!err)
497 trace_bpf_map_update_elem(map, ufd, key, value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700498free_value:
499 kfree(value);
500free_key:
501 kfree(key);
502err_put:
503 fdput(f);
504 return err;
505}
506
507#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
508
509static int map_delete_elem(union bpf_attr *attr)
510{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100511 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700512 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700513 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200514 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700515 void *key;
516 int err;
517
518 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
519 return -EINVAL;
520
Daniel Borkmann592867b2015-09-08 18:00:09 +0200521 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100522 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700523 if (IS_ERR(map))
524 return PTR_ERR(map);
525
526 err = -ENOMEM;
527 key = kmalloc(map->key_size, GFP_USER);
528 if (!key)
529 goto err_put;
530
531 err = -EFAULT;
532 if (copy_from_user(key, ukey, map->key_size) != 0)
533 goto free_key;
534
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800535 preempt_disable();
536 __this_cpu_inc(bpf_prog_active);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700537 rcu_read_lock();
538 err = map->ops->map_delete_elem(map, key);
539 rcu_read_unlock();
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800540 __this_cpu_dec(bpf_prog_active);
541 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700542
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100543 if (!err)
544 trace_bpf_map_delete_elem(map, ufd, key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700545free_key:
546 kfree(key);
547err_put:
548 fdput(f);
549 return err;
550}
551
552/* last field in 'union bpf_attr' used by this command */
553#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
554
555static int map_get_next_key(union bpf_attr *attr)
556{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100557 void __user *ukey = u64_to_user_ptr(attr->key);
558 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700559 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700560 struct bpf_map *map;
561 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200562 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700563 int err;
564
565 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
566 return -EINVAL;
567
Daniel Borkmann592867b2015-09-08 18:00:09 +0200568 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100569 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700570 if (IS_ERR(map))
571 return PTR_ERR(map);
572
Teng Qin8fe45922017-04-24 19:00:37 -0700573 if (ukey) {
574 err = -ENOMEM;
575 key = kmalloc(map->key_size, GFP_USER);
576 if (!key)
577 goto err_put;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700578
Teng Qin8fe45922017-04-24 19:00:37 -0700579 err = -EFAULT;
580 if (copy_from_user(key, ukey, map->key_size) != 0)
581 goto free_key;
582 } else {
583 key = NULL;
584 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700585
586 err = -ENOMEM;
587 next_key = kmalloc(map->key_size, GFP_USER);
588 if (!next_key)
589 goto free_key;
590
591 rcu_read_lock();
592 err = map->ops->map_get_next_key(map, key, next_key);
593 rcu_read_unlock();
594 if (err)
595 goto free_next_key;
596
597 err = -EFAULT;
598 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
599 goto free_next_key;
600
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100601 trace_bpf_map_next_key(map, ufd, key, next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700602 err = 0;
603
604free_next_key:
605 kfree(next_key);
606free_key:
607 kfree(key);
608err_put:
609 fdput(f);
610 return err;
611}
612
Johannes Bergbe9370a2017-04-11 15:34:57 +0200613static const struct bpf_verifier_ops * const bpf_prog_types[] = {
614#define BPF_PROG_TYPE(_id, _ops) \
615 [_id] = &_ops,
Johannes Berg40077e02017-04-11 15:34:58 +0200616#define BPF_MAP_TYPE(_id, _ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +0200617#include <linux/bpf_types.h>
618#undef BPF_PROG_TYPE
Johannes Berg40077e02017-04-11 15:34:58 +0200619#undef BPF_MAP_TYPE
Johannes Bergbe9370a2017-04-11 15:34:57 +0200620};
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700621
622static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
623{
Johannes Bergbe9370a2017-04-11 15:34:57 +0200624 if (type >= ARRAY_SIZE(bpf_prog_types) || !bpf_prog_types[type])
625 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700626
Johannes Bergbe9370a2017-04-11 15:34:57 +0200627 prog->aux->ops = bpf_prog_types[type];
628 prog->type = type;
629 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700630}
631
632/* drop refcnt on maps used by eBPF program and free auxilary data */
633static void free_used_maps(struct bpf_prog_aux *aux)
634{
635 int i;
636
637 for (i = 0; i < aux->used_map_cnt; i++)
638 bpf_map_put(aux->used_maps[i]);
639
640 kfree(aux->used_maps);
641}
642
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100643int __bpf_prog_charge(struct user_struct *user, u32 pages)
644{
645 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
646 unsigned long user_bufs;
647
648 if (user) {
649 user_bufs = atomic_long_add_return(pages, &user->locked_vm);
650 if (user_bufs > memlock_limit) {
651 atomic_long_sub(pages, &user->locked_vm);
652 return -EPERM;
653 }
654 }
655
656 return 0;
657}
658
659void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
660{
661 if (user)
662 atomic_long_sub(pages, &user->locked_vm);
663}
664
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700665static int bpf_prog_charge_memlock(struct bpf_prog *prog)
666{
667 struct user_struct *user = get_current_user();
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100668 int ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700669
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100670 ret = __bpf_prog_charge(user, prog->pages);
671 if (ret) {
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700672 free_uid(user);
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100673 return ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700674 }
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100675
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700676 prog->aux->user = user;
677 return 0;
678}
679
680static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
681{
682 struct user_struct *user = prog->aux->user;
683
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100684 __bpf_prog_uncharge(user, prog->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700685 free_uid(user);
686}
687
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700688static int bpf_prog_alloc_id(struct bpf_prog *prog)
689{
690 int id;
691
692 spin_lock_bh(&prog_idr_lock);
693 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
694 if (id > 0)
695 prog->aux->id = id;
696 spin_unlock_bh(&prog_idr_lock);
697
698 /* id is in [1, INT_MAX) */
699 if (WARN_ON_ONCE(!id))
700 return -ENOSPC;
701
702 return id > 0 ? 0 : id;
703}
704
705static void bpf_prog_free_id(struct bpf_prog *prog)
706{
707 /* cBPF to eBPF migrations are currently not in the idr store. */
708 if (!prog->aux->id)
709 return;
710
711 spin_lock_bh(&prog_idr_lock);
712 idr_remove(&prog_idr, prog->aux->id);
713 spin_unlock_bh(&prog_idr_lock);
714}
715
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200716static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700717{
718 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
719
720 free_used_maps(aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700721 bpf_prog_uncharge_memlock(aux->prog);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700722 bpf_prog_free(aux->prog);
723}
724
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700725void bpf_prog_put(struct bpf_prog *prog)
726{
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100727 if (atomic_dec_and_test(&prog->aux->refcnt)) {
728 trace_bpf_prog_put_rcu(prog);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700729 bpf_prog_free_id(prog);
Daniel Borkmann74451e662017-02-16 22:24:50 +0100730 bpf_prog_kallsyms_del(prog);
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200731 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100732 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700733}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +0100734EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700735
736static int bpf_prog_release(struct inode *inode, struct file *filp)
737{
738 struct bpf_prog *prog = filp->private_data;
739
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200740 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700741 return 0;
742}
743
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100744#ifdef CONFIG_PROC_FS
745static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
746{
747 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100748 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100749
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100750 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100751 seq_printf(m,
752 "prog_type:\t%u\n"
753 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100754 "prog_tag:\t%s\n"
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100755 "memlock:\t%llu\n",
756 prog->type,
757 prog->jited,
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100758 prog_tag,
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100759 prog->pages * 1ULL << PAGE_SHIFT);
760}
761#endif
762
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700763static const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100764#ifdef CONFIG_PROC_FS
765 .show_fdinfo = bpf_prog_show_fdinfo,
766#endif
767 .release = bpf_prog_release,
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700768};
769
Daniel Borkmannb2197752015-10-29 14:58:09 +0100770int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100771{
772 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
773 O_RDWR | O_CLOEXEC);
774}
775
Daniel Borkmann113214b2016-06-30 17:24:44 +0200776static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700777{
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700778 if (!f.file)
779 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700780 if (f.file->f_op != &bpf_prog_fops) {
781 fdput(f);
782 return ERR_PTR(-EINVAL);
783 }
784
Daniel Borkmannc2101292015-10-29 14:58:07 +0100785 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700786}
787
Brenden Blanco59d36562016-07-19 12:16:46 -0700788struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700789{
Brenden Blanco59d36562016-07-19 12:16:46 -0700790 if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
791 atomic_sub(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700792 return ERR_PTR(-EBUSY);
793 }
794 return prog;
795}
Brenden Blanco59d36562016-07-19 12:16:46 -0700796EXPORT_SYMBOL_GPL(bpf_prog_add);
797
Daniel Borkmannc5405942016-11-09 22:02:34 +0100798void bpf_prog_sub(struct bpf_prog *prog, int i)
799{
800 /* Only to be used for undoing previous bpf_prog_add() in some
801 * error path. We still know that another entity in our call
802 * path holds a reference to the program, thus atomic_sub() can
803 * be safely used in such cases!
804 */
805 WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
806}
807EXPORT_SYMBOL_GPL(bpf_prog_sub);
808
Brenden Blanco59d36562016-07-19 12:16:46 -0700809struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
810{
811 return bpf_prog_add(prog, 1);
812}
Daniel Borkmann97bc4022016-11-19 01:45:00 +0100813EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700814
Daniel Borkmann113214b2016-06-30 17:24:44 +0200815static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700816{
817 struct fd f = fdget(ufd);
818 struct bpf_prog *prog;
819
Daniel Borkmann113214b2016-06-30 17:24:44 +0200820 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700821 if (IS_ERR(prog))
822 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200823 if (type && prog->type != *type) {
824 prog = ERR_PTR(-EINVAL);
825 goto out;
826 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700827
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700828 prog = bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +0200829out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700830 fdput(f);
831 return prog;
832}
Daniel Borkmann113214b2016-06-30 17:24:44 +0200833
834struct bpf_prog *bpf_prog_get(u32 ufd)
835{
836 return __bpf_prog_get(ufd, NULL);
837}
838
839struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
840{
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100841 struct bpf_prog *prog = __bpf_prog_get(ufd, &type);
842
843 if (!IS_ERR(prog))
844 trace_bpf_prog_get_type(prog);
845 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200846}
847EXPORT_SYMBOL_GPL(bpf_prog_get_type);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700848
849/* last field in 'union bpf_attr' used by this command */
David S. Millere07b98d2017-05-10 11:38:07 -0700850#define BPF_PROG_LOAD_LAST_FIELD prog_flags
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700851
852static int bpf_prog_load(union bpf_attr *attr)
853{
854 enum bpf_prog_type type = attr->prog_type;
855 struct bpf_prog *prog;
856 int err;
857 char license[128];
858 bool is_gpl;
859
860 if (CHECK_ATTR(BPF_PROG_LOAD))
861 return -EINVAL;
862
David S. Millere07b98d2017-05-10 11:38:07 -0700863 if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
864 return -EINVAL;
865
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700866 /* copy eBPF program license from user space */
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100867 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700868 sizeof(license) - 1) < 0)
869 return -EFAULT;
870 license[sizeof(license) - 1] = 0;
871
872 /* eBPF programs must be GPL compatible to use GPL-ed functions */
873 is_gpl = license_is_gpl_compatible(license);
874
Daniel Borkmannef0915c2016-12-07 01:15:44 +0100875 if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS)
876 return -E2BIG;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700877
Alexei Starovoitov25415172015-03-25 12:49:20 -0700878 if (type == BPF_PROG_TYPE_KPROBE &&
879 attr->kern_version != LINUX_VERSION_CODE)
880 return -EINVAL;
881
Chenbo Feng80b7d812017-05-31 18:16:00 -0700882 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
883 type != BPF_PROG_TYPE_CGROUP_SKB &&
884 !capable(CAP_SYS_ADMIN))
Alexei Starovoitov1be7f752015-10-07 22:23:21 -0700885 return -EPERM;
886
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700887 /* plain bpf_prog allocation */
888 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
889 if (!prog)
890 return -ENOMEM;
891
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700892 err = bpf_prog_charge_memlock(prog);
893 if (err)
894 goto free_prog_nouncharge;
895
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700896 prog->len = attr->insn_cnt;
897
898 err = -EFAULT;
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100899 if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
Daniel Borkmannaafe6ae2016-12-18 01:52:57 +0100900 bpf_prog_insn_size(prog)) != 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700901 goto free_prog;
902
903 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200904 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700905
906 atomic_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200907 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700908
909 /* find program type: socket_filter vs tracing_filter */
910 err = find_prog_type(type, prog);
911 if (err < 0)
912 goto free_prog;
913
914 /* run eBPF verifier */
Alexei Starovoitov9bac3d62015-03-13 11:57:42 -0700915 err = bpf_check(&prog, attr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700916 if (err < 0)
917 goto free_used_maps;
918
919 /* eBPF program is ready to be JITed */
Daniel Borkmannd1c55ab2016-05-13 19:08:31 +0200920 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -0700921 if (err < 0)
922 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700923
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700924 err = bpf_prog_alloc_id(prog);
925 if (err)
926 goto free_used_maps;
927
Daniel Borkmannaa797812015-10-29 14:58:06 +0100928 err = bpf_prog_new_fd(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700929 if (err < 0)
930 /* failed to allocate fd */
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700931 goto free_id;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700932
Daniel Borkmann74451e662017-02-16 22:24:50 +0100933 bpf_prog_kallsyms_add(prog);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100934 trace_bpf_prog_load(prog, err);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700935 return err;
936
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700937free_id:
938 bpf_prog_free_id(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700939free_used_maps:
940 free_used_maps(prog->aux);
941free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700942 bpf_prog_uncharge_memlock(prog);
943free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700944 bpf_prog_free(prog);
945 return err;
946}
947
Daniel Borkmannb2197752015-10-29 14:58:09 +0100948#define BPF_OBJ_LAST_FIELD bpf_fd
949
950static int bpf_obj_pin(const union bpf_attr *attr)
951{
952 if (CHECK_ATTR(BPF_OBJ))
953 return -EINVAL;
954
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100955 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +0100956}
957
958static int bpf_obj_get(const union bpf_attr *attr)
959{
960 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0)
961 return -EINVAL;
962
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100963 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +0100964}
965
Daniel Mackf4324552016-11-23 16:52:27 +0100966#ifdef CONFIG_CGROUP_BPF
967
Alexei Starovoitov7f677632017-02-10 20:28:24 -0800968#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
Daniel Mackf4324552016-11-23 16:52:27 +0100969
970static int bpf_prog_attach(const union bpf_attr *attr)
971{
Alexei Starovoitov7f677632017-02-10 20:28:24 -0800972 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +0100973 struct bpf_prog *prog;
974 struct cgroup *cgrp;
Alexei Starovoitov7f677632017-02-10 20:28:24 -0800975 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +0100976
977 if (!capable(CAP_NET_ADMIN))
978 return -EPERM;
979
980 if (CHECK_ATTR(BPF_PROG_ATTACH))
981 return -EINVAL;
982
Alexei Starovoitov7f677632017-02-10 20:28:24 -0800983 if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE)
984 return -EINVAL;
985
Daniel Mackf4324552016-11-23 16:52:27 +0100986 switch (attr->attach_type) {
987 case BPF_CGROUP_INET_INGRESS:
988 case BPF_CGROUP_INET_EGRESS:
David Ahernb2cd1252016-12-01 08:48:03 -0800989 ptype = BPF_PROG_TYPE_CGROUP_SKB;
Daniel Mackf4324552016-11-23 16:52:27 +0100990 break;
David Ahern610236582016-12-01 08:48:04 -0800991 case BPF_CGROUP_INET_SOCK_CREATE:
992 ptype = BPF_PROG_TYPE_CGROUP_SOCK;
993 break;
Daniel Mackf4324552016-11-23 16:52:27 +0100994 default:
995 return -EINVAL;
996 }
997
David Ahernb2cd1252016-12-01 08:48:03 -0800998 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
999 if (IS_ERR(prog))
1000 return PTR_ERR(prog);
1001
1002 cgrp = cgroup_get_from_fd(attr->target_fd);
1003 if (IS_ERR(cgrp)) {
1004 bpf_prog_put(prog);
1005 return PTR_ERR(cgrp);
1006 }
1007
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001008 ret = cgroup_bpf_update(cgrp, prog, attr->attach_type,
1009 attr->attach_flags & BPF_F_ALLOW_OVERRIDE);
1010 if (ret)
1011 bpf_prog_put(prog);
David Ahernb2cd1252016-12-01 08:48:03 -08001012 cgroup_put(cgrp);
1013
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001014 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001015}
1016
1017#define BPF_PROG_DETACH_LAST_FIELD attach_type
1018
1019static int bpf_prog_detach(const union bpf_attr *attr)
1020{
1021 struct cgroup *cgrp;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001022 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001023
1024 if (!capable(CAP_NET_ADMIN))
1025 return -EPERM;
1026
1027 if (CHECK_ATTR(BPF_PROG_DETACH))
1028 return -EINVAL;
1029
1030 switch (attr->attach_type) {
1031 case BPF_CGROUP_INET_INGRESS:
1032 case BPF_CGROUP_INET_EGRESS:
David Ahern610236582016-12-01 08:48:04 -08001033 case BPF_CGROUP_INET_SOCK_CREATE:
Daniel Mackf4324552016-11-23 16:52:27 +01001034 cgrp = cgroup_get_from_fd(attr->target_fd);
1035 if (IS_ERR(cgrp))
1036 return PTR_ERR(cgrp);
1037
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001038 ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
Daniel Mackf4324552016-11-23 16:52:27 +01001039 cgroup_put(cgrp);
1040 break;
1041
1042 default:
1043 return -EINVAL;
1044 }
1045
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001046 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001047}
1048#endif /* CONFIG_CGROUP_BPF */
1049
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001050#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
1051
1052static int bpf_prog_test_run(const union bpf_attr *attr,
1053 union bpf_attr __user *uattr)
1054{
1055 struct bpf_prog *prog;
1056 int ret = -ENOTSUPP;
1057
1058 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
1059 return -EINVAL;
1060
1061 prog = bpf_prog_get(attr->test.prog_fd);
1062 if (IS_ERR(prog))
1063 return PTR_ERR(prog);
1064
1065 if (prog->aux->ops->test_run)
1066 ret = prog->aux->ops->test_run(prog, attr, uattr);
1067
1068 bpf_prog_put(prog);
1069 return ret;
1070}
1071
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001072SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
1073{
1074 union bpf_attr attr = {};
1075 int err;
1076
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07001077 if (!capable(CAP_SYS_ADMIN) && sysctl_unprivileged_bpf_disabled)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001078 return -EPERM;
1079
1080 if (!access_ok(VERIFY_READ, uattr, 1))
1081 return -EFAULT;
1082
1083 if (size > PAGE_SIZE) /* silly large */
1084 return -E2BIG;
1085
1086 /* If we're handed a bigger struct than we know of,
1087 * ensure all the unknown bits are 0 - i.e. new
1088 * user-space does not rely on any kernel feature
1089 * extensions we dont know about yet.
1090 */
1091 if (size > sizeof(attr)) {
1092 unsigned char __user *addr;
1093 unsigned char __user *end;
1094 unsigned char val;
1095
1096 addr = (void __user *)uattr + sizeof(attr);
1097 end = (void __user *)uattr + size;
1098
1099 for (; addr < end; addr++) {
1100 err = get_user(val, addr);
1101 if (err)
1102 return err;
1103 if (val)
1104 return -E2BIG;
1105 }
1106 size = sizeof(attr);
1107 }
1108
1109 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
1110 if (copy_from_user(&attr, uattr, size) != 0)
1111 return -EFAULT;
1112
1113 switch (cmd) {
1114 case BPF_MAP_CREATE:
1115 err = map_create(&attr);
1116 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001117 case BPF_MAP_LOOKUP_ELEM:
1118 err = map_lookup_elem(&attr);
1119 break;
1120 case BPF_MAP_UPDATE_ELEM:
1121 err = map_update_elem(&attr);
1122 break;
1123 case BPF_MAP_DELETE_ELEM:
1124 err = map_delete_elem(&attr);
1125 break;
1126 case BPF_MAP_GET_NEXT_KEY:
1127 err = map_get_next_key(&attr);
1128 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001129 case BPF_PROG_LOAD:
1130 err = bpf_prog_load(&attr);
1131 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01001132 case BPF_OBJ_PIN:
1133 err = bpf_obj_pin(&attr);
1134 break;
1135 case BPF_OBJ_GET:
1136 err = bpf_obj_get(&attr);
1137 break;
Daniel Mackf4324552016-11-23 16:52:27 +01001138#ifdef CONFIG_CGROUP_BPF
1139 case BPF_PROG_ATTACH:
1140 err = bpf_prog_attach(&attr);
1141 break;
1142 case BPF_PROG_DETACH:
1143 err = bpf_prog_detach(&attr);
1144 break;
1145#endif
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001146 case BPF_PROG_TEST_RUN:
1147 err = bpf_prog_test_run(&attr, uattr);
1148 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001149 default:
1150 err = -EINVAL;
1151 break;
1152 }
1153
1154 return err;
1155}