blob: 1802bb9c47d943f65a3e10d6b406872650dbe76b [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
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700138static void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700139{
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700140 if (do_idr_lock)
141 spin_lock_bh(&map_idr_lock);
142 else
143 __acquire(&map_idr_lock);
144
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700145 idr_remove(&map_idr, map->id);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700146
147 if (do_idr_lock)
148 spin_unlock_bh(&map_idr_lock);
149 else
150 __release(&map_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700151}
152
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700153/* called from workqueue */
154static void bpf_map_free_deferred(struct work_struct *work)
155{
156 struct bpf_map *map = container_of(work, struct bpf_map, work);
157
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700158 bpf_map_uncharge_memlock(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700159 /* implementation dependent freeing */
160 map->ops->map_free(map);
161}
162
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100163static void bpf_map_put_uref(struct bpf_map *map)
164{
165 if (atomic_dec_and_test(&map->usercnt)) {
166 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
167 bpf_fd_array_map_clear(map);
168 }
169}
170
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700171/* decrement map refcnt and schedule it for freeing via workqueue
172 * (unrelying map implementation ops->map_free() might sleep)
173 */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700174static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700175{
176 if (atomic_dec_and_test(&map->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700177 /* bpf_map_free_id() must be called first */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700178 bpf_map_free_id(map, do_idr_lock);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700179 INIT_WORK(&map->work, bpf_map_free_deferred);
180 schedule_work(&map->work);
181 }
182}
183
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700184void bpf_map_put(struct bpf_map *map)
185{
186 __bpf_map_put(map, true);
187}
188
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100189void bpf_map_put_with_uref(struct bpf_map *map)
190{
191 bpf_map_put_uref(map);
192 bpf_map_put(map);
193}
194
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700195static int bpf_map_release(struct inode *inode, struct file *filp)
196{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200197 struct bpf_map *map = filp->private_data;
198
199 if (map->ops->map_release)
200 map->ops->map_release(map, filp);
201
202 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700203 return 0;
204}
205
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100206#ifdef CONFIG_PROC_FS
207static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
208{
209 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100210 const struct bpf_array *array;
211 u32 owner_prog_type = 0;
212
213 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
214 array = container_of(map, struct bpf_array, map);
215 owner_prog_type = array->owner_prog_type;
216 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100217
218 seq_printf(m,
219 "map_type:\t%u\n"
220 "key_size:\t%u\n"
221 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100222 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100223 "map_flags:\t%#x\n"
224 "memlock:\t%llu\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100225 map->map_type,
226 map->key_size,
227 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100228 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100229 map->map_flags,
230 map->pages * 1ULL << PAGE_SHIFT);
231
232 if (owner_prog_type)
233 seq_printf(m, "owner_prog_type:\t%u\n",
234 owner_prog_type);
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100235}
236#endif
237
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700238static const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100239#ifdef CONFIG_PROC_FS
240 .show_fdinfo = bpf_map_show_fdinfo,
241#endif
242 .release = bpf_map_release,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700243};
244
Daniel Borkmannb2197752015-10-29 14:58:09 +0100245int bpf_map_new_fd(struct bpf_map *map)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100246{
247 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
248 O_RDWR | O_CLOEXEC);
249}
250
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700251/* helper macro to check that unused fields 'union bpf_attr' are zero */
252#define CHECK_ATTR(CMD) \
253 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
254 sizeof(attr->CMD##_LAST_FIELD), 0, \
255 sizeof(*attr) - \
256 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
257 sizeof(attr->CMD##_LAST_FIELD)) != NULL
258
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700259#define BPF_MAP_CREATE_LAST_FIELD inner_map_fd
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700260/* called via syscall */
261static int map_create(union bpf_attr *attr)
262{
263 struct bpf_map *map;
264 int err;
265
266 err = CHECK_ATTR(BPF_MAP_CREATE);
267 if (err)
268 return -EINVAL;
269
270 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
271 map = find_and_alloc_map(attr);
272 if (IS_ERR(map))
273 return PTR_ERR(map);
274
275 atomic_set(&map->refcnt, 1);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100276 atomic_set(&map->usercnt, 1);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700277
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700278 err = bpf_map_charge_memlock(map);
279 if (err)
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100280 goto free_map_nouncharge;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700281
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700282 err = bpf_map_alloc_id(map);
283 if (err)
284 goto free_map;
285
Daniel Borkmannaa797812015-10-29 14:58:06 +0100286 err = bpf_map_new_fd(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700287 if (err < 0) {
288 /* failed to allocate fd.
289 * bpf_map_put() is needed because the above
290 * bpf_map_alloc_id() has published the map
291 * to the userspace and the userspace may
292 * have refcnt-ed it through BPF_MAP_GET_FD_BY_ID.
293 */
294 bpf_map_put(map);
295 return err;
296 }
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700297
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100298 trace_bpf_map_create(map, err);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700299 return err;
300
301free_map:
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100302 bpf_map_uncharge_memlock(map);
303free_map_nouncharge:
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700304 map->ops->map_free(map);
305 return err;
306}
307
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700308/* if error is returned, fd is released.
309 * On success caller should complete fd access with matching fdput()
310 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100311struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700312{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700313 if (!f.file)
314 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700315 if (f.file->f_op != &bpf_map_fops) {
316 fdput(f);
317 return ERR_PTR(-EINVAL);
318 }
319
Daniel Borkmannc2101292015-10-29 14:58:07 +0100320 return f.file->private_data;
321}
322
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700323/* prog's and map's refcnt limit */
324#define BPF_MAX_REFCNT 32768
325
326struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100327{
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700328 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
329 atomic_dec(&map->refcnt);
330 return ERR_PTR(-EBUSY);
331 }
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100332 if (uref)
333 atomic_inc(&map->usercnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700334 return map;
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100335}
336
337struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100338{
339 struct fd f = fdget(ufd);
340 struct bpf_map *map;
341
342 map = __bpf_map_get(f);
343 if (IS_ERR(map))
344 return map;
345
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700346 map = bpf_map_inc(map, true);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100347 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700348
349 return map;
350}
351
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700352/* map_idr_lock should have been held */
353static struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map,
354 bool uref)
355{
356 int refold;
357
358 refold = __atomic_add_unless(&map->refcnt, 1, 0);
359
360 if (refold >= BPF_MAX_REFCNT) {
361 __bpf_map_put(map, false);
362 return ERR_PTR(-EBUSY);
363 }
364
365 if (!refold)
366 return ERR_PTR(-ENOENT);
367
368 if (uref)
369 atomic_inc(&map->usercnt);
370
371 return map;
372}
373
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -0800374int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
375{
376 return -ENOTSUPP;
377}
378
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700379/* last field in 'union bpf_attr' used by this command */
380#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
381
382static int map_lookup_elem(union bpf_attr *attr)
383{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100384 void __user *ukey = u64_to_user_ptr(attr->key);
385 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700386 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700387 struct bpf_map *map;
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800388 void *key, *value, *ptr;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800389 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200390 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700391 int err;
392
393 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
394 return -EINVAL;
395
Daniel Borkmann592867b2015-09-08 18:00:09 +0200396 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100397 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700398 if (IS_ERR(map))
399 return PTR_ERR(map);
400
401 err = -ENOMEM;
402 key = kmalloc(map->key_size, GFP_USER);
403 if (!key)
404 goto err_put;
405
406 err = -EFAULT;
407 if (copy_from_user(key, ukey, map->key_size) != 0)
408 goto free_key;
409
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800410 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800411 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800412 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
413 value_size = round_up(map->value_size, 8) * num_possible_cpus();
414 else
415 value_size = map->value_size;
416
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800417 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800418 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700419 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800420 goto free_key;
421
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800422 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
423 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800424 err = bpf_percpu_hash_copy(map, key, value);
425 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
426 err = bpf_percpu_array_copy(map, key, value);
Alexei Starovoitov557c0c62016-03-07 21:57:17 -0800427 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
428 err = bpf_stackmap_copy(map, key, value);
Martin KaFai Laubcc6b1b2017-03-22 10:00:34 -0700429 } else if (map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
430 map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700431 err = -ENOTSUPP;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800432 } else {
433 rcu_read_lock();
434 ptr = map->ops->map_lookup_elem(map, key);
435 if (ptr)
436 memcpy(value, ptr, value_size);
437 rcu_read_unlock();
438 err = ptr ? 0 : -ENOENT;
439 }
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800440
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800441 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800442 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700443
444 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800445 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800446 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700447
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100448 trace_bpf_map_lookup_elem(map, ufd, key, value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700449 err = 0;
450
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800451free_value:
452 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700453free_key:
454 kfree(key);
455err_put:
456 fdput(f);
457 return err;
458}
459
Alexei Starovoitov3274f522014-11-13 17:36:44 -0800460#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700461
462static int map_update_elem(union bpf_attr *attr)
463{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100464 void __user *ukey = u64_to_user_ptr(attr->key);
465 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700466 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700467 struct bpf_map *map;
468 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800469 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200470 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700471 int err;
472
473 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
474 return -EINVAL;
475
Daniel Borkmann592867b2015-09-08 18:00:09 +0200476 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100477 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700478 if (IS_ERR(map))
479 return PTR_ERR(map);
480
481 err = -ENOMEM;
482 key = kmalloc(map->key_size, GFP_USER);
483 if (!key)
484 goto err_put;
485
486 err = -EFAULT;
487 if (copy_from_user(key, ukey, map->key_size) != 0)
488 goto free_key;
489
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800490 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800491 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800492 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
493 value_size = round_up(map->value_size, 8) * num_possible_cpus();
494 else
495 value_size = map->value_size;
496
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700497 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800498 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700499 if (!value)
500 goto free_key;
501
502 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800503 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700504 goto free_value;
505
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800506 /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
507 * inside bpf map update or delete otherwise deadlocks are possible
508 */
509 preempt_disable();
510 __this_cpu_inc(bpf_prog_active);
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800511 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
512 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800513 err = bpf_percpu_hash_update(map, key, value, attr->flags);
514 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
515 err = bpf_percpu_array_update(map, key, value, attr->flags);
Daniel Borkmannd056a782016-06-15 22:47:13 +0200516 } else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
Martin KaFai Lau4ed8ec52016-06-30 10:28:43 -0700517 map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
Martin KaFai Lau56f668d2017-03-22 10:00:33 -0700518 map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY ||
519 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS) {
Daniel Borkmannd056a782016-06-15 22:47:13 +0200520 rcu_read_lock();
521 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
522 attr->flags);
523 rcu_read_unlock();
Martin KaFai Laubcc6b1b2017-03-22 10:00:34 -0700524 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
525 rcu_read_lock();
526 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
527 attr->flags);
528 rcu_read_unlock();
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800529 } else {
530 rcu_read_lock();
531 err = map->ops->map_update_elem(map, key, value, attr->flags);
532 rcu_read_unlock();
533 }
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800534 __this_cpu_dec(bpf_prog_active);
535 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700536
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100537 if (!err)
538 trace_bpf_map_update_elem(map, ufd, key, value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700539free_value:
540 kfree(value);
541free_key:
542 kfree(key);
543err_put:
544 fdput(f);
545 return err;
546}
547
548#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
549
550static int map_delete_elem(union bpf_attr *attr)
551{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100552 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700553 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700554 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200555 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700556 void *key;
557 int err;
558
559 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
560 return -EINVAL;
561
Daniel Borkmann592867b2015-09-08 18:00:09 +0200562 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100563 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700564 if (IS_ERR(map))
565 return PTR_ERR(map);
566
567 err = -ENOMEM;
568 key = kmalloc(map->key_size, GFP_USER);
569 if (!key)
570 goto err_put;
571
572 err = -EFAULT;
573 if (copy_from_user(key, ukey, map->key_size) != 0)
574 goto free_key;
575
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800576 preempt_disable();
577 __this_cpu_inc(bpf_prog_active);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700578 rcu_read_lock();
579 err = map->ops->map_delete_elem(map, key);
580 rcu_read_unlock();
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800581 __this_cpu_dec(bpf_prog_active);
582 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700583
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100584 if (!err)
585 trace_bpf_map_delete_elem(map, ufd, key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700586free_key:
587 kfree(key);
588err_put:
589 fdput(f);
590 return err;
591}
592
593/* last field in 'union bpf_attr' used by this command */
594#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
595
596static int map_get_next_key(union bpf_attr *attr)
597{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100598 void __user *ukey = u64_to_user_ptr(attr->key);
599 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700600 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700601 struct bpf_map *map;
602 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200603 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700604 int err;
605
606 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
607 return -EINVAL;
608
Daniel Borkmann592867b2015-09-08 18:00:09 +0200609 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100610 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700611 if (IS_ERR(map))
612 return PTR_ERR(map);
613
Teng Qin8fe45922017-04-24 19:00:37 -0700614 if (ukey) {
615 err = -ENOMEM;
616 key = kmalloc(map->key_size, GFP_USER);
617 if (!key)
618 goto err_put;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700619
Teng Qin8fe45922017-04-24 19:00:37 -0700620 err = -EFAULT;
621 if (copy_from_user(key, ukey, map->key_size) != 0)
622 goto free_key;
623 } else {
624 key = NULL;
625 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700626
627 err = -ENOMEM;
628 next_key = kmalloc(map->key_size, GFP_USER);
629 if (!next_key)
630 goto free_key;
631
632 rcu_read_lock();
633 err = map->ops->map_get_next_key(map, key, next_key);
634 rcu_read_unlock();
635 if (err)
636 goto free_next_key;
637
638 err = -EFAULT;
639 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
640 goto free_next_key;
641
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100642 trace_bpf_map_next_key(map, ufd, key, next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700643 err = 0;
644
645free_next_key:
646 kfree(next_key);
647free_key:
648 kfree(key);
649err_put:
650 fdput(f);
651 return err;
652}
653
Johannes Bergbe9370a2017-04-11 15:34:57 +0200654static const struct bpf_verifier_ops * const bpf_prog_types[] = {
655#define BPF_PROG_TYPE(_id, _ops) \
656 [_id] = &_ops,
Johannes Berg40077e02017-04-11 15:34:58 +0200657#define BPF_MAP_TYPE(_id, _ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +0200658#include <linux/bpf_types.h>
659#undef BPF_PROG_TYPE
Johannes Berg40077e02017-04-11 15:34:58 +0200660#undef BPF_MAP_TYPE
Johannes Bergbe9370a2017-04-11 15:34:57 +0200661};
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700662
663static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
664{
Johannes Bergbe9370a2017-04-11 15:34:57 +0200665 if (type >= ARRAY_SIZE(bpf_prog_types) || !bpf_prog_types[type])
666 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700667
Johannes Bergbe9370a2017-04-11 15:34:57 +0200668 prog->aux->ops = bpf_prog_types[type];
669 prog->type = type;
670 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700671}
672
673/* drop refcnt on maps used by eBPF program and free auxilary data */
674static void free_used_maps(struct bpf_prog_aux *aux)
675{
676 int i;
677
678 for (i = 0; i < aux->used_map_cnt; i++)
679 bpf_map_put(aux->used_maps[i]);
680
681 kfree(aux->used_maps);
682}
683
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100684int __bpf_prog_charge(struct user_struct *user, u32 pages)
685{
686 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
687 unsigned long user_bufs;
688
689 if (user) {
690 user_bufs = atomic_long_add_return(pages, &user->locked_vm);
691 if (user_bufs > memlock_limit) {
692 atomic_long_sub(pages, &user->locked_vm);
693 return -EPERM;
694 }
695 }
696
697 return 0;
698}
699
700void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
701{
702 if (user)
703 atomic_long_sub(pages, &user->locked_vm);
704}
705
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700706static int bpf_prog_charge_memlock(struct bpf_prog *prog)
707{
708 struct user_struct *user = get_current_user();
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100709 int ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700710
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100711 ret = __bpf_prog_charge(user, prog->pages);
712 if (ret) {
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700713 free_uid(user);
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100714 return ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700715 }
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100716
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700717 prog->aux->user = user;
718 return 0;
719}
720
721static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
722{
723 struct user_struct *user = prog->aux->user;
724
Daniel Borkmann5ccb0712016-12-18 01:52:58 +0100725 __bpf_prog_uncharge(user, prog->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700726 free_uid(user);
727}
728
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700729static int bpf_prog_alloc_id(struct bpf_prog *prog)
730{
731 int id;
732
733 spin_lock_bh(&prog_idr_lock);
734 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
735 if (id > 0)
736 prog->aux->id = id;
737 spin_unlock_bh(&prog_idr_lock);
738
739 /* id is in [1, INT_MAX) */
740 if (WARN_ON_ONCE(!id))
741 return -ENOSPC;
742
743 return id > 0 ? 0 : id;
744}
745
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700746static void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700747{
748 /* cBPF to eBPF migrations are currently not in the idr store. */
749 if (!prog->aux->id)
750 return;
751
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700752 if (do_idr_lock)
753 spin_lock_bh(&prog_idr_lock);
754 else
755 __acquire(&prog_idr_lock);
756
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700757 idr_remove(&prog_idr, prog->aux->id);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700758
759 if (do_idr_lock)
760 spin_unlock_bh(&prog_idr_lock);
761 else
762 __release(&prog_idr_lock);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700763}
764
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200765static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700766{
767 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
768
769 free_used_maps(aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700770 bpf_prog_uncharge_memlock(aux->prog);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700771 bpf_prog_free(aux->prog);
772}
773
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700774static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700775{
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100776 if (atomic_dec_and_test(&prog->aux->refcnt)) {
777 trace_bpf_prog_put_rcu(prog);
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700778 /* bpf_prog_free_id() must be called first */
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700779 bpf_prog_free_id(prog, do_idr_lock);
Daniel Borkmann74451e662017-02-16 22:24:50 +0100780 bpf_prog_kallsyms_del(prog);
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200781 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100782 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700783}
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700784
785void bpf_prog_put(struct bpf_prog *prog)
786{
787 __bpf_prog_put(prog, true);
788}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +0100789EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700790
791static int bpf_prog_release(struct inode *inode, struct file *filp)
792{
793 struct bpf_prog *prog = filp->private_data;
794
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200795 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700796 return 0;
797}
798
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100799#ifdef CONFIG_PROC_FS
800static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
801{
802 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100803 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100804
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100805 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100806 seq_printf(m,
807 "prog_type:\t%u\n"
808 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100809 "prog_tag:\t%s\n"
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100810 "memlock:\t%llu\n",
811 prog->type,
812 prog->jited,
Daniel Borkmannf1f77142017-01-13 23:38:15 +0100813 prog_tag,
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100814 prog->pages * 1ULL << PAGE_SHIFT);
815}
816#endif
817
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700818static const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +0100819#ifdef CONFIG_PROC_FS
820 .show_fdinfo = bpf_prog_show_fdinfo,
821#endif
822 .release = bpf_prog_release,
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700823};
824
Daniel Borkmannb2197752015-10-29 14:58:09 +0100825int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100826{
827 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
828 O_RDWR | O_CLOEXEC);
829}
830
Daniel Borkmann113214b2016-06-30 17:24:44 +0200831static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700832{
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700833 if (!f.file)
834 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700835 if (f.file->f_op != &bpf_prog_fops) {
836 fdput(f);
837 return ERR_PTR(-EINVAL);
838 }
839
Daniel Borkmannc2101292015-10-29 14:58:07 +0100840 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700841}
842
Brenden Blanco59d36562016-07-19 12:16:46 -0700843struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700844{
Brenden Blanco59d36562016-07-19 12:16:46 -0700845 if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
846 atomic_sub(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700847 return ERR_PTR(-EBUSY);
848 }
849 return prog;
850}
Brenden Blanco59d36562016-07-19 12:16:46 -0700851EXPORT_SYMBOL_GPL(bpf_prog_add);
852
Daniel Borkmannc5405942016-11-09 22:02:34 +0100853void bpf_prog_sub(struct bpf_prog *prog, int i)
854{
855 /* Only to be used for undoing previous bpf_prog_add() in some
856 * error path. We still know that another entity in our call
857 * path holds a reference to the program, thus atomic_sub() can
858 * be safely used in such cases!
859 */
860 WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
861}
862EXPORT_SYMBOL_GPL(bpf_prog_sub);
863
Brenden Blanco59d36562016-07-19 12:16:46 -0700864struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
865{
866 return bpf_prog_add(prog, 1);
867}
Daniel Borkmann97bc4022016-11-19 01:45:00 +0100868EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700869
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -0700870/* prog_idr_lock should have been held */
871static struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
872{
873 int refold;
874
875 refold = __atomic_add_unless(&prog->aux->refcnt, 1, 0);
876
877 if (refold >= BPF_MAX_REFCNT) {
878 __bpf_prog_put(prog, false);
879 return ERR_PTR(-EBUSY);
880 }
881
882 if (!refold)
883 return ERR_PTR(-ENOENT);
884
885 return prog;
886}
887
Daniel Borkmann113214b2016-06-30 17:24:44 +0200888static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700889{
890 struct fd f = fdget(ufd);
891 struct bpf_prog *prog;
892
Daniel Borkmann113214b2016-06-30 17:24:44 +0200893 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700894 if (IS_ERR(prog))
895 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200896 if (type && prog->type != *type) {
897 prog = ERR_PTR(-EINVAL);
898 goto out;
899 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700900
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700901 prog = bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +0200902out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700903 fdput(f);
904 return prog;
905}
Daniel Borkmann113214b2016-06-30 17:24:44 +0200906
907struct bpf_prog *bpf_prog_get(u32 ufd)
908{
909 return __bpf_prog_get(ufd, NULL);
910}
911
912struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
913{
Daniel Borkmanna67edbf2017-01-25 02:28:18 +0100914 struct bpf_prog *prog = __bpf_prog_get(ufd, &type);
915
916 if (!IS_ERR(prog))
917 trace_bpf_prog_get_type(prog);
918 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200919}
920EXPORT_SYMBOL_GPL(bpf_prog_get_type);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700921
922/* last field in 'union bpf_attr' used by this command */
David S. Millere07b98d2017-05-10 11:38:07 -0700923#define BPF_PROG_LOAD_LAST_FIELD prog_flags
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700924
925static int bpf_prog_load(union bpf_attr *attr)
926{
927 enum bpf_prog_type type = attr->prog_type;
928 struct bpf_prog *prog;
929 int err;
930 char license[128];
931 bool is_gpl;
932
933 if (CHECK_ATTR(BPF_PROG_LOAD))
934 return -EINVAL;
935
David S. Millere07b98d2017-05-10 11:38:07 -0700936 if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
937 return -EINVAL;
938
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700939 /* copy eBPF program license from user space */
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100940 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700941 sizeof(license) - 1) < 0)
942 return -EFAULT;
943 license[sizeof(license) - 1] = 0;
944
945 /* eBPF programs must be GPL compatible to use GPL-ed functions */
946 is_gpl = license_is_gpl_compatible(license);
947
Daniel Borkmannef0915c2016-12-07 01:15:44 +0100948 if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS)
949 return -E2BIG;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700950
Alexei Starovoitov25415172015-03-25 12:49:20 -0700951 if (type == BPF_PROG_TYPE_KPROBE &&
952 attr->kern_version != LINUX_VERSION_CODE)
953 return -EINVAL;
954
Chenbo Feng80b7d812017-05-31 18:16:00 -0700955 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
956 type != BPF_PROG_TYPE_CGROUP_SKB &&
957 !capable(CAP_SYS_ADMIN))
Alexei Starovoitov1be7f752015-10-07 22:23:21 -0700958 return -EPERM;
959
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700960 /* plain bpf_prog allocation */
961 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
962 if (!prog)
963 return -ENOMEM;
964
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700965 err = bpf_prog_charge_memlock(prog);
966 if (err)
967 goto free_prog_nouncharge;
968
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700969 prog->len = attr->insn_cnt;
970
971 err = -EFAULT;
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100972 if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
Daniel Borkmannaafe6ae2016-12-18 01:52:57 +0100973 bpf_prog_insn_size(prog)) != 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700974 goto free_prog;
975
976 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200977 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700978
979 atomic_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200980 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700981
982 /* find program type: socket_filter vs tracing_filter */
983 err = find_prog_type(type, prog);
984 if (err < 0)
985 goto free_prog;
986
987 /* run eBPF verifier */
Alexei Starovoitov9bac3d62015-03-13 11:57:42 -0700988 err = bpf_check(&prog, attr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700989 if (err < 0)
990 goto free_used_maps;
991
992 /* eBPF program is ready to be JITed */
Daniel Borkmannd1c55ab2016-05-13 19:08:31 +0200993 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -0700994 if (err < 0)
995 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700996
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -0700997 err = bpf_prog_alloc_id(prog);
998 if (err)
999 goto free_used_maps;
1000
Daniel Borkmannaa797812015-10-29 14:58:06 +01001001 err = bpf_prog_new_fd(prog);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001002 if (err < 0) {
1003 /* failed to allocate fd.
1004 * bpf_prog_put() is needed because the above
1005 * bpf_prog_alloc_id() has published the prog
1006 * to the userspace and the userspace may
1007 * have refcnt-ed it through BPF_PROG_GET_FD_BY_ID.
1008 */
1009 bpf_prog_put(prog);
1010 return err;
1011 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001012
Daniel Borkmann74451e662017-02-16 22:24:50 +01001013 bpf_prog_kallsyms_add(prog);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001014 trace_bpf_prog_load(prog, err);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001015 return err;
1016
1017free_used_maps:
1018 free_used_maps(prog->aux);
1019free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001020 bpf_prog_uncharge_memlock(prog);
1021free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001022 bpf_prog_free(prog);
1023 return err;
1024}
1025
Daniel Borkmannb2197752015-10-29 14:58:09 +01001026#define BPF_OBJ_LAST_FIELD bpf_fd
1027
1028static int bpf_obj_pin(const union bpf_attr *attr)
1029{
1030 if (CHECK_ATTR(BPF_OBJ))
1031 return -EINVAL;
1032
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001033 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01001034}
1035
1036static int bpf_obj_get(const union bpf_attr *attr)
1037{
1038 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0)
1039 return -EINVAL;
1040
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001041 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01001042}
1043
Daniel Mackf4324552016-11-23 16:52:27 +01001044#ifdef CONFIG_CGROUP_BPF
1045
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001046#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
Daniel Mackf4324552016-11-23 16:52:27 +01001047
1048static int bpf_prog_attach(const union bpf_attr *attr)
1049{
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001050 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01001051 struct bpf_prog *prog;
1052 struct cgroup *cgrp;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001053 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001054
1055 if (!capable(CAP_NET_ADMIN))
1056 return -EPERM;
1057
1058 if (CHECK_ATTR(BPF_PROG_ATTACH))
1059 return -EINVAL;
1060
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001061 if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE)
1062 return -EINVAL;
1063
Daniel Mackf4324552016-11-23 16:52:27 +01001064 switch (attr->attach_type) {
1065 case BPF_CGROUP_INET_INGRESS:
1066 case BPF_CGROUP_INET_EGRESS:
David Ahernb2cd1252016-12-01 08:48:03 -08001067 ptype = BPF_PROG_TYPE_CGROUP_SKB;
Daniel Mackf4324552016-11-23 16:52:27 +01001068 break;
David Ahern610236582016-12-01 08:48:04 -08001069 case BPF_CGROUP_INET_SOCK_CREATE:
1070 ptype = BPF_PROG_TYPE_CGROUP_SOCK;
1071 break;
Daniel Mackf4324552016-11-23 16:52:27 +01001072 default:
1073 return -EINVAL;
1074 }
1075
David Ahernb2cd1252016-12-01 08:48:03 -08001076 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
1077 if (IS_ERR(prog))
1078 return PTR_ERR(prog);
1079
1080 cgrp = cgroup_get_from_fd(attr->target_fd);
1081 if (IS_ERR(cgrp)) {
1082 bpf_prog_put(prog);
1083 return PTR_ERR(cgrp);
1084 }
1085
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001086 ret = cgroup_bpf_update(cgrp, prog, attr->attach_type,
1087 attr->attach_flags & BPF_F_ALLOW_OVERRIDE);
1088 if (ret)
1089 bpf_prog_put(prog);
David Ahernb2cd1252016-12-01 08:48:03 -08001090 cgroup_put(cgrp);
1091
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001092 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001093}
1094
1095#define BPF_PROG_DETACH_LAST_FIELD attach_type
1096
1097static int bpf_prog_detach(const union bpf_attr *attr)
1098{
1099 struct cgroup *cgrp;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001100 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001101
1102 if (!capable(CAP_NET_ADMIN))
1103 return -EPERM;
1104
1105 if (CHECK_ATTR(BPF_PROG_DETACH))
1106 return -EINVAL;
1107
1108 switch (attr->attach_type) {
1109 case BPF_CGROUP_INET_INGRESS:
1110 case BPF_CGROUP_INET_EGRESS:
David Ahern610236582016-12-01 08:48:04 -08001111 case BPF_CGROUP_INET_SOCK_CREATE:
Daniel Mackf4324552016-11-23 16:52:27 +01001112 cgrp = cgroup_get_from_fd(attr->target_fd);
1113 if (IS_ERR(cgrp))
1114 return PTR_ERR(cgrp);
1115
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001116 ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
Daniel Mackf4324552016-11-23 16:52:27 +01001117 cgroup_put(cgrp);
1118 break;
1119
1120 default:
1121 return -EINVAL;
1122 }
1123
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001124 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001125}
1126#endif /* CONFIG_CGROUP_BPF */
1127
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001128#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
1129
1130static int bpf_prog_test_run(const union bpf_attr *attr,
1131 union bpf_attr __user *uattr)
1132{
1133 struct bpf_prog *prog;
1134 int ret = -ENOTSUPP;
1135
1136 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
1137 return -EINVAL;
1138
1139 prog = bpf_prog_get(attr->test.prog_fd);
1140 if (IS_ERR(prog))
1141 return PTR_ERR(prog);
1142
1143 if (prog->aux->ops->test_run)
1144 ret = prog->aux->ops->test_run(prog, attr, uattr);
1145
1146 bpf_prog_put(prog);
1147 return ret;
1148}
1149
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001150#define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
1151
1152static int bpf_obj_get_next_id(const union bpf_attr *attr,
1153 union bpf_attr __user *uattr,
1154 struct idr *idr,
1155 spinlock_t *lock)
1156{
1157 u32 next_id = attr->start_id;
1158 int err = 0;
1159
1160 if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX)
1161 return -EINVAL;
1162
1163 if (!capable(CAP_SYS_ADMIN))
1164 return -EPERM;
1165
1166 next_id++;
1167 spin_lock_bh(lock);
1168 if (!idr_get_next(idr, &next_id))
1169 err = -ENOENT;
1170 spin_unlock_bh(lock);
1171
1172 if (!err)
1173 err = put_user(next_id, &uattr->next_id);
1174
1175 return err;
1176}
1177
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001178#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
1179
1180static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
1181{
1182 struct bpf_prog *prog;
1183 u32 id = attr->prog_id;
1184 int fd;
1185
1186 if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID))
1187 return -EINVAL;
1188
1189 if (!capable(CAP_SYS_ADMIN))
1190 return -EPERM;
1191
1192 spin_lock_bh(&prog_idr_lock);
1193 prog = idr_find(&prog_idr, id);
1194 if (prog)
1195 prog = bpf_prog_inc_not_zero(prog);
1196 else
1197 prog = ERR_PTR(-ENOENT);
1198 spin_unlock_bh(&prog_idr_lock);
1199
1200 if (IS_ERR(prog))
1201 return PTR_ERR(prog);
1202
1203 fd = bpf_prog_new_fd(prog);
1204 if (fd < 0)
1205 bpf_prog_put(prog);
1206
1207 return fd;
1208}
1209
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001210#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD map_id
1211
1212static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
1213{
1214 struct bpf_map *map;
1215 u32 id = attr->map_id;
1216 int fd;
1217
1218 if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID))
1219 return -EINVAL;
1220
1221 if (!capable(CAP_SYS_ADMIN))
1222 return -EPERM;
1223
1224 spin_lock_bh(&map_idr_lock);
1225 map = idr_find(&map_idr, id);
1226 if (map)
1227 map = bpf_map_inc_not_zero(map, true);
1228 else
1229 map = ERR_PTR(-ENOENT);
1230 spin_unlock_bh(&map_idr_lock);
1231
1232 if (IS_ERR(map))
1233 return PTR_ERR(map);
1234
1235 fd = bpf_map_new_fd(map);
1236 if (fd < 0)
1237 bpf_map_put(map);
1238
1239 return fd;
1240}
1241
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001242SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
1243{
1244 union bpf_attr attr = {};
1245 int err;
1246
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07001247 if (!capable(CAP_SYS_ADMIN) && sysctl_unprivileged_bpf_disabled)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001248 return -EPERM;
1249
1250 if (!access_ok(VERIFY_READ, uattr, 1))
1251 return -EFAULT;
1252
1253 if (size > PAGE_SIZE) /* silly large */
1254 return -E2BIG;
1255
1256 /* If we're handed a bigger struct than we know of,
1257 * ensure all the unknown bits are 0 - i.e. new
1258 * user-space does not rely on any kernel feature
1259 * extensions we dont know about yet.
1260 */
1261 if (size > sizeof(attr)) {
1262 unsigned char __user *addr;
1263 unsigned char __user *end;
1264 unsigned char val;
1265
1266 addr = (void __user *)uattr + sizeof(attr);
1267 end = (void __user *)uattr + size;
1268
1269 for (; addr < end; addr++) {
1270 err = get_user(val, addr);
1271 if (err)
1272 return err;
1273 if (val)
1274 return -E2BIG;
1275 }
1276 size = sizeof(attr);
1277 }
1278
1279 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
1280 if (copy_from_user(&attr, uattr, size) != 0)
1281 return -EFAULT;
1282
1283 switch (cmd) {
1284 case BPF_MAP_CREATE:
1285 err = map_create(&attr);
1286 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001287 case BPF_MAP_LOOKUP_ELEM:
1288 err = map_lookup_elem(&attr);
1289 break;
1290 case BPF_MAP_UPDATE_ELEM:
1291 err = map_update_elem(&attr);
1292 break;
1293 case BPF_MAP_DELETE_ELEM:
1294 err = map_delete_elem(&attr);
1295 break;
1296 case BPF_MAP_GET_NEXT_KEY:
1297 err = map_get_next_key(&attr);
1298 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001299 case BPF_PROG_LOAD:
1300 err = bpf_prog_load(&attr);
1301 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01001302 case BPF_OBJ_PIN:
1303 err = bpf_obj_pin(&attr);
1304 break;
1305 case BPF_OBJ_GET:
1306 err = bpf_obj_get(&attr);
1307 break;
Daniel Mackf4324552016-11-23 16:52:27 +01001308#ifdef CONFIG_CGROUP_BPF
1309 case BPF_PROG_ATTACH:
1310 err = bpf_prog_attach(&attr);
1311 break;
1312 case BPF_PROG_DETACH:
1313 err = bpf_prog_detach(&attr);
1314 break;
1315#endif
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001316 case BPF_PROG_TEST_RUN:
1317 err = bpf_prog_test_run(&attr, uattr);
1318 break;
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001319 case BPF_PROG_GET_NEXT_ID:
1320 err = bpf_obj_get_next_id(&attr, uattr,
1321 &prog_idr, &prog_idr_lock);
1322 break;
1323 case BPF_MAP_GET_NEXT_ID:
1324 err = bpf_obj_get_next_id(&attr, uattr,
1325 &map_idr, &map_idr_lock);
1326 break;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001327 case BPF_PROG_GET_FD_BY_ID:
1328 err = bpf_prog_get_fd_by_id(&attr);
1329 break;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001330 case BPF_MAP_GET_FD_BY_ID:
1331 err = bpf_map_get_fd_by_id(&attr);
1332 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001333 default:
1334 err = -EINVAL;
1335 break;
1336 }
1337
1338 return err;
1339}