blob: 52aa47b98a71fa5a9d6c28979779e0f4cbb12d00 [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>
13#include <linux/syscalls.h>
14#include <linux/slab.h>
Daniel Borkmann251d00b2017-01-18 15:14:17 +010015#include <linux/vmalloc.h>
16#include <linux/mmzone.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070017#include <linux/anon_inodes.h>
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -070018#include <linux/file.h>
Alexei Starovoitov09756af2014-09-26 00:17:00 -070019#include <linux/license.h>
20#include <linux/filter.h>
Alexei Starovoitov25415172015-03-25 12:49:20 -070021#include <linux/version.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070022
Chenbo Feng4672ded2017-10-18 13:00:22 -070023#define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY)
24
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080025DEFINE_PER_CPU(int, bpf_prog_active);
26
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070027int sysctl_unprivileged_bpf_disabled __read_mostly;
28
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070029static LIST_HEAD(bpf_map_types);
30
31static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
32{
33 struct bpf_map_type_list *tl;
34 struct bpf_map *map;
35
36 list_for_each_entry(tl, &bpf_map_types, list_node) {
37 if (tl->type == attr->map_type) {
38 map = tl->ops->map_alloc(attr);
39 if (IS_ERR(map))
40 return map;
41 map->ops = tl->ops;
42 map->map_type = attr->map_type;
43 return map;
44 }
45 }
46 return ERR_PTR(-EINVAL);
47}
48
49/* boot time registration of different map implementations */
50void bpf_register_map_type(struct bpf_map_type_list *tl)
51{
52 list_add(&tl->list_node, &bpf_map_types);
53}
54
Daniel Borkmann251d00b2017-01-18 15:14:17 +010055void *bpf_map_area_alloc(size_t size)
56{
57 /* We definitely need __GFP_NORETRY, so OOM killer doesn't
58 * trigger under memory pressure as we really just want to
59 * fail instead.
60 */
61 const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
62 void *area;
63
64 if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
65 area = kmalloc(size, GFP_USER | flags);
66 if (area != NULL)
67 return area;
68 }
69
70 return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
71 PAGE_KERNEL);
72}
73
74void bpf_map_area_free(void *area)
75{
76 kvfree(area);
77}
78
Alexei Starovoitov6c905982016-03-07 21:57:15 -080079int bpf_map_precharge_memlock(u32 pages)
80{
81 struct user_struct *user = get_current_user();
82 unsigned long memlock_limit, cur;
83
84 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
85 cur = atomic_long_read(&user->locked_vm);
86 free_uid(user);
87 if (cur + pages > memlock_limit)
88 return -EPERM;
89 return 0;
90}
91
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -070092static int bpf_map_charge_memlock(struct bpf_map *map)
93{
94 struct user_struct *user = get_current_user();
95 unsigned long memlock_limit;
96
97 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
98
99 atomic_long_add(map->pages, &user->locked_vm);
100
101 if (atomic_long_read(&user->locked_vm) > memlock_limit) {
102 atomic_long_sub(map->pages, &user->locked_vm);
103 free_uid(user);
104 return -EPERM;
105 }
106 map->user = user;
107 return 0;
108}
109
110static void bpf_map_uncharge_memlock(struct bpf_map *map)
111{
112 struct user_struct *user = map->user;
113
114 atomic_long_sub(map->pages, &user->locked_vm);
115 free_uid(user);
116}
117
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700118/* called from workqueue */
119static void bpf_map_free_deferred(struct work_struct *work)
120{
121 struct bpf_map *map = container_of(work, struct bpf_map, work);
122
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700123 bpf_map_uncharge_memlock(map);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700124 security_bpf_map_free(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700125 /* implementation dependent freeing */
126 map->ops->map_free(map);
127}
128
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100129static void bpf_map_put_uref(struct bpf_map *map)
130{
131 if (atomic_dec_and_test(&map->usercnt)) {
132 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
133 bpf_fd_array_map_clear(map);
134 }
135}
136
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700137/* decrement map refcnt and schedule it for freeing via workqueue
138 * (unrelying map implementation ops->map_free() might sleep)
139 */
140void bpf_map_put(struct bpf_map *map)
141{
142 if (atomic_dec_and_test(&map->refcnt)) {
143 INIT_WORK(&map->work, bpf_map_free_deferred);
144 schedule_work(&map->work);
145 }
146}
147
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100148void bpf_map_put_with_uref(struct bpf_map *map)
149{
150 bpf_map_put_uref(map);
151 bpf_map_put(map);
152}
153
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700154static int bpf_map_release(struct inode *inode, struct file *filp)
155{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200156 struct bpf_map *map = filp->private_data;
157
158 if (map->ops->map_release)
159 map->ops->map_release(map, filp);
160
161 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700162 return 0;
163}
164
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100165#ifdef CONFIG_PROC_FS
166static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
167{
168 const struct bpf_map *map = filp->private_data;
169
170 seq_printf(m,
171 "map_type:\t%u\n"
172 "key_size:\t%u\n"
173 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100174 "max_entries:\t%u\n"
175 "map_flags:\t%#x\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100176 map->map_type,
177 map->key_size,
178 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100179 map->max_entries,
180 map->map_flags);
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100181}
182#endif
183
Chenbo Feng4672ded2017-10-18 13:00:22 -0700184static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
185 loff_t *ppos)
186{
187 /* We need this handler such that alloc_file() enables
188 * f_mode with FMODE_CAN_READ.
189 */
190 return -EINVAL;
191}
192
193static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
194 size_t siz, loff_t *ppos)
195{
196 /* We need this handler such that alloc_file() enables
197 * f_mode with FMODE_CAN_WRITE.
198 */
199 return -EINVAL;
200}
201
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700202static const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100203#ifdef CONFIG_PROC_FS
204 .show_fdinfo = bpf_map_show_fdinfo,
205#endif
206 .release = bpf_map_release,
Chenbo Feng4672ded2017-10-18 13:00:22 -0700207 .read = bpf_dummy_read,
208 .write = bpf_dummy_write,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700209};
210
Chenbo Feng4672ded2017-10-18 13:00:22 -0700211int bpf_map_new_fd(struct bpf_map *map, int flags)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100212{
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700213 int ret;
214
215 ret = security_bpf_map(map, OPEN_FMODE(flags));
216 if (ret < 0)
217 return ret;
218
Daniel Borkmannaa797812015-10-29 14:58:06 +0100219 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
Chenbo Feng4672ded2017-10-18 13:00:22 -0700220 flags | O_CLOEXEC);
221}
222
223int bpf_get_file_flag(int flags)
224{
225 if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
226 return -EINVAL;
227 if (flags & BPF_F_RDONLY)
228 return O_RDONLY;
229 if (flags & BPF_F_WRONLY)
230 return O_WRONLY;
231 return O_RDWR;
Daniel Borkmannaa797812015-10-29 14:58:06 +0100232}
233
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700234/* helper macro to check that unused fields 'union bpf_attr' are zero */
235#define CHECK_ATTR(CMD) \
236 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
237 sizeof(attr->CMD##_LAST_FIELD), 0, \
238 sizeof(*attr) - \
239 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
240 sizeof(attr->CMD##_LAST_FIELD)) != NULL
241
Alexei Starovoitov6c905982016-03-07 21:57:15 -0800242#define BPF_MAP_CREATE_LAST_FIELD map_flags
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700243/* called via syscall */
244static int map_create(union bpf_attr *attr)
245{
246 struct bpf_map *map;
Chenbo Feng4672ded2017-10-18 13:00:22 -0700247 int f_flags;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700248 int err;
249
250 err = CHECK_ATTR(BPF_MAP_CREATE);
251 if (err)
252 return -EINVAL;
253
Chenbo Feng4672ded2017-10-18 13:00:22 -0700254 f_flags = bpf_get_file_flag(attr->map_flags);
255 if (f_flags < 0)
256 return f_flags;
257
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700258 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
259 map = find_and_alloc_map(attr);
260 if (IS_ERR(map))
261 return PTR_ERR(map);
262
263 atomic_set(&map->refcnt, 1);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100264 atomic_set(&map->usercnt, 1);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700265
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700266 err = security_bpf_map_alloc(map);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700267 if (err)
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100268 goto free_map_nouncharge;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700269
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700270 err = bpf_map_charge_memlock(map);
271 if (err)
272 goto free_map_sec;
273
Chenbo Feng4672ded2017-10-18 13:00:22 -0700274 err = bpf_map_new_fd(map, f_flags);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700275 if (err < 0)
276 /* failed to allocate fd */
277 goto free_map;
278
279 return err;
280
281free_map:
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100282 bpf_map_uncharge_memlock(map);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700283free_map_sec:
284 security_bpf_map_free(map);
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100285free_map_nouncharge:
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700286 map->ops->map_free(map);
287 return err;
288}
289
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700290/* if error is returned, fd is released.
291 * On success caller should complete fd access with matching fdput()
292 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100293struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700294{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700295 if (!f.file)
296 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700297 if (f.file->f_op != &bpf_map_fops) {
298 fdput(f);
299 return ERR_PTR(-EINVAL);
300 }
301
Daniel Borkmannc2101292015-10-29 14:58:07 +0100302 return f.file->private_data;
303}
304
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700305/* prog's and map's refcnt limit */
306#define BPF_MAX_REFCNT 32768
307
308struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100309{
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700310 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
311 atomic_dec(&map->refcnt);
312 return ERR_PTR(-EBUSY);
313 }
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100314 if (uref)
315 atomic_inc(&map->usercnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700316 return map;
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100317}
318
319struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100320{
321 struct fd f = fdget(ufd);
322 struct bpf_map *map;
323
324 map = __bpf_map_get(f);
325 if (IS_ERR(map))
326 return map;
327
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700328 map = bpf_map_inc(map, true);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100329 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700330
331 return map;
332}
333
334/* helper to convert user pointers passed inside __aligned_u64 fields */
335static void __user *u64_to_ptr(__u64 val)
336{
337 return (void __user *) (unsigned long) val;
338}
339
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -0800340int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
341{
342 return -ENOTSUPP;
343}
344
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700345/* last field in 'union bpf_attr' used by this command */
346#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
347
348static int map_lookup_elem(union bpf_attr *attr)
349{
350 void __user *ukey = u64_to_ptr(attr->key);
351 void __user *uvalue = u64_to_ptr(attr->value);
352 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700353 struct bpf_map *map;
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800354 void *key, *value, *ptr;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800355 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200356 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700357 int err;
358
359 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
360 return -EINVAL;
361
Daniel Borkmann592867b2015-09-08 18:00:09 +0200362 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100363 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700364 if (IS_ERR(map))
365 return PTR_ERR(map);
366
Chenbo Feng4672ded2017-10-18 13:00:22 -0700367 if (!(f.file->f_mode & FMODE_CAN_READ)) {
368 err = -EPERM;
369 goto err_put;
370 }
371
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700372 err = -ENOMEM;
373 key = kmalloc(map->key_size, GFP_USER);
374 if (!key)
375 goto err_put;
376
377 err = -EFAULT;
378 if (copy_from_user(key, ukey, map->key_size) != 0)
379 goto free_key;
380
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800381 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
382 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
383 value_size = round_up(map->value_size, 8) * num_possible_cpus();
384 else
385 value_size = map->value_size;
386
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800387 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800388 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700389 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800390 goto free_key;
391
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800392 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
393 err = bpf_percpu_hash_copy(map, key, value);
394 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
395 err = bpf_percpu_array_copy(map, key, value);
Alexei Starovoitov557c0c62016-03-07 21:57:17 -0800396 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
397 err = bpf_stackmap_copy(map, key, value);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800398 } else {
399 rcu_read_lock();
400 ptr = map->ops->map_lookup_elem(map, key);
401 if (ptr)
402 memcpy(value, ptr, value_size);
403 rcu_read_unlock();
404 err = ptr ? 0 : -ENOENT;
405 }
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800406
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800407 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800408 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700409
410 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800411 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800412 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700413
414 err = 0;
415
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800416free_value:
417 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700418free_key:
419 kfree(key);
420err_put:
421 fdput(f);
422 return err;
423}
424
Alexei Starovoitov3274f522014-11-13 17:36:44 -0800425#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700426
427static int map_update_elem(union bpf_attr *attr)
428{
429 void __user *ukey = u64_to_ptr(attr->key);
430 void __user *uvalue = u64_to_ptr(attr->value);
431 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700432 struct bpf_map *map;
433 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800434 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200435 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700436 int err;
437
438 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
439 return -EINVAL;
440
Daniel Borkmann592867b2015-09-08 18:00:09 +0200441 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100442 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700443 if (IS_ERR(map))
444 return PTR_ERR(map);
445
Chenbo Feng4672ded2017-10-18 13:00:22 -0700446 if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
447 err = -EPERM;
448 goto err_put;
449 }
450
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700451 err = -ENOMEM;
452 key = kmalloc(map->key_size, GFP_USER);
453 if (!key)
454 goto err_put;
455
456 err = -EFAULT;
457 if (copy_from_user(key, ukey, map->key_size) != 0)
458 goto free_key;
459
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800460 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
461 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
462 value_size = round_up(map->value_size, 8) * num_possible_cpus();
463 else
464 value_size = map->value_size;
465
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700466 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800467 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700468 if (!value)
469 goto free_key;
470
471 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800472 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700473 goto free_value;
474
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800475 /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
476 * inside bpf map update or delete otherwise deadlocks are possible
477 */
478 preempt_disable();
479 __this_cpu_inc(bpf_prog_active);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800480 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) {
481 err = bpf_percpu_hash_update(map, key, value, attr->flags);
482 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
483 err = bpf_percpu_array_update(map, key, value, attr->flags);
Daniel Borkmannd056a782016-06-15 22:47:13 +0200484 } else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
Martin KaFai Lau4ed8ec52016-06-30 10:28:43 -0700485 map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
486 map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY) {
Daniel Borkmannd056a782016-06-15 22:47:13 +0200487 rcu_read_lock();
488 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
489 attr->flags);
490 rcu_read_unlock();
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800491 } else {
492 rcu_read_lock();
493 err = map->ops->map_update_elem(map, key, value, attr->flags);
494 rcu_read_unlock();
495 }
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800496 __this_cpu_dec(bpf_prog_active);
497 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700498
499free_value:
500 kfree(value);
501free_key:
502 kfree(key);
503err_put:
504 fdput(f);
505 return err;
506}
507
508#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
509
510static int map_delete_elem(union bpf_attr *attr)
511{
512 void __user *ukey = u64_to_ptr(attr->key);
513 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700514 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200515 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700516 void *key;
517 int err;
518
519 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
520 return -EINVAL;
521
Daniel Borkmann592867b2015-09-08 18:00:09 +0200522 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100523 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700524 if (IS_ERR(map))
525 return PTR_ERR(map);
526
Chenbo Feng4672ded2017-10-18 13:00:22 -0700527 if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
528 err = -EPERM;
529 goto err_put;
530 }
531
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700532 err = -ENOMEM;
533 key = kmalloc(map->key_size, GFP_USER);
534 if (!key)
535 goto err_put;
536
537 err = -EFAULT;
538 if (copy_from_user(key, ukey, map->key_size) != 0)
539 goto free_key;
540
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800541 preempt_disable();
542 __this_cpu_inc(bpf_prog_active);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700543 rcu_read_lock();
544 err = map->ops->map_delete_elem(map, key);
545 rcu_read_unlock();
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800546 __this_cpu_dec(bpf_prog_active);
547 preempt_enable();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700548
549free_key:
550 kfree(key);
551err_put:
552 fdput(f);
553 return err;
554}
555
556/* last field in 'union bpf_attr' used by this command */
557#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
558
559static int map_get_next_key(union bpf_attr *attr)
560{
561 void __user *ukey = u64_to_ptr(attr->key);
562 void __user *unext_key = u64_to_ptr(attr->next_key);
563 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700564 struct bpf_map *map;
565 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200566 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700567 int err;
568
569 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
570 return -EINVAL;
571
Daniel Borkmann592867b2015-09-08 18:00:09 +0200572 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100573 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700574 if (IS_ERR(map))
575 return PTR_ERR(map);
576
Chenbo Feng4672ded2017-10-18 13:00:22 -0700577 if (!(f.file->f_mode & FMODE_CAN_READ)) {
578 err = -EPERM;
579 goto err_put;
580 }
581
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700582 err = -ENOMEM;
583 key = kmalloc(map->key_size, GFP_USER);
584 if (!key)
585 goto err_put;
586
587 err = -EFAULT;
588 if (copy_from_user(key, ukey, map->key_size) != 0)
589 goto free_key;
590
591 err = -ENOMEM;
592 next_key = kmalloc(map->key_size, GFP_USER);
593 if (!next_key)
594 goto free_key;
595
596 rcu_read_lock();
597 err = map->ops->map_get_next_key(map, key, next_key);
598 rcu_read_unlock();
599 if (err)
600 goto free_next_key;
601
602 err = -EFAULT;
603 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
604 goto free_next_key;
605
606 err = 0;
607
608free_next_key:
609 kfree(next_key);
610free_key:
611 kfree(key);
612err_put:
613 fdput(f);
614 return err;
615}
616
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700617static LIST_HEAD(bpf_prog_types);
618
619static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
620{
621 struct bpf_prog_type_list *tl;
622
623 list_for_each_entry(tl, &bpf_prog_types, list_node) {
624 if (tl->type == type) {
625 prog->aux->ops = tl->ops;
Daniel Borkmann24701ec2015-03-01 12:31:47 +0100626 prog->type = type;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700627 return 0;
628 }
629 }
Daniel Borkmann24701ec2015-03-01 12:31:47 +0100630
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700631 return -EINVAL;
632}
633
634void bpf_register_prog_type(struct bpf_prog_type_list *tl)
635{
636 list_add(&tl->list_node, &bpf_prog_types);
637}
638
Alexei Starovoitov0a542a82014-09-26 00:17:01 -0700639/* fixup insn->imm field of bpf_call instructions:
640 * if (insn->imm == BPF_FUNC_map_lookup_elem)
641 * insn->imm = bpf_map_lookup_elem - __bpf_call_base;
642 * else if (insn->imm == BPF_FUNC_map_update_elem)
643 * insn->imm = bpf_map_update_elem - __bpf_call_base;
644 * else ...
645 *
646 * this function is called after eBPF program passed verification
647 */
648static void fixup_bpf_calls(struct bpf_prog *prog)
649{
650 const struct bpf_func_proto *fn;
651 int i;
652
653 for (i = 0; i < prog->len; i++) {
654 struct bpf_insn *insn = &prog->insnsi[i];
655
656 if (insn->code == (BPF_JMP | BPF_CALL)) {
657 /* we reach here when program has bpf_call instructions
658 * and it passed bpf_check(), means that
659 * ops->get_func_proto must have been supplied, check it
660 */
661 BUG_ON(!prog->aux->ops->get_func_proto);
662
Daniel Borkmannc46646d2015-09-30 01:41:51 +0200663 if (insn->imm == BPF_FUNC_get_route_realm)
664 prog->dst_needed = 1;
Daniel Borkmann3ad00402015-10-08 01:20:39 +0200665 if (insn->imm == BPF_FUNC_get_prandom_u32)
666 bpf_user_rnd_init_once();
Alexei Starovoitov04fd61a2015-05-19 16:59:03 -0700667 if (insn->imm == BPF_FUNC_tail_call) {
668 /* mark bpf_tail_call as different opcode
669 * to avoid conditional branch in
670 * interpeter for every normal call
671 * and to prevent accidental JITing by
672 * JIT compiler that doesn't support
673 * bpf_tail_call yet
674 */
675 insn->imm = 0;
676 insn->code |= BPF_X;
677 continue;
678 }
679
Alexei Starovoitov0a542a82014-09-26 00:17:01 -0700680 fn = prog->aux->ops->get_func_proto(insn->imm);
681 /* all functions that have prototype and verifier allowed
682 * programs to call them, must be real in-kernel functions
683 */
684 BUG_ON(!fn->func);
685 insn->imm = fn->func - __bpf_call_base;
686 }
687 }
688}
689
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700690/* drop refcnt on maps used by eBPF program and free auxilary data */
691static void free_used_maps(struct bpf_prog_aux *aux)
692{
693 int i;
694
695 for (i = 0; i < aux->used_map_cnt; i++)
696 bpf_map_put(aux->used_maps[i]);
697
698 kfree(aux->used_maps);
699}
700
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700701static int bpf_prog_charge_memlock(struct bpf_prog *prog)
702{
703 struct user_struct *user = get_current_user();
704 unsigned long memlock_limit;
705
706 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
707
708 atomic_long_add(prog->pages, &user->locked_vm);
709 if (atomic_long_read(&user->locked_vm) > memlock_limit) {
710 atomic_long_sub(prog->pages, &user->locked_vm);
711 free_uid(user);
712 return -EPERM;
713 }
714 prog->aux->user = user;
715 return 0;
716}
717
718static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
719{
720 struct user_struct *user = prog->aux->user;
721
722 atomic_long_sub(prog->pages, &user->locked_vm);
723 free_uid(user);
724}
725
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200726static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700727{
728 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
729
730 free_used_maps(aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700731 bpf_prog_uncharge_memlock(aux->prog);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700732 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700733 bpf_prog_free(aux->prog);
734}
735
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700736void bpf_prog_put(struct bpf_prog *prog)
737{
Daniel Borkmanne9d8afa2015-10-29 14:58:08 +0100738 if (atomic_dec_and_test(&prog->aux->refcnt))
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200739 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700740}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +0100741EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700742
743static int bpf_prog_release(struct inode *inode, struct file *filp)
744{
745 struct bpf_prog *prog = filp->private_data;
746
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200747 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700748 return 0;
749}
750
751static const struct file_operations bpf_prog_fops = {
752 .release = bpf_prog_release,
Chenbo Feng4672ded2017-10-18 13:00:22 -0700753 .read = bpf_dummy_read,
754 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700755};
756
Daniel Borkmannb2197752015-10-29 14:58:09 +0100757int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100758{
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700759 int ret;
760
761 ret = security_bpf_prog(prog);
762 if (ret < 0)
763 return ret;
764
Daniel Borkmannaa797812015-10-29 14:58:06 +0100765 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
766 O_RDWR | O_CLOEXEC);
767}
768
Daniel Borkmann113214b2016-06-30 17:24:44 +0200769static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700770{
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700771 if (!f.file)
772 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700773 if (f.file->f_op != &bpf_prog_fops) {
774 fdput(f);
775 return ERR_PTR(-EINVAL);
776 }
777
Daniel Borkmannc2101292015-10-29 14:58:07 +0100778 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700779}
780
Brenden Blanco59d36562016-07-19 12:16:46 -0700781struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700782{
Brenden Blanco59d36562016-07-19 12:16:46 -0700783 if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
784 atomic_sub(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700785 return ERR_PTR(-EBUSY);
786 }
787 return prog;
788}
Brenden Blanco59d36562016-07-19 12:16:46 -0700789EXPORT_SYMBOL_GPL(bpf_prog_add);
790
791struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
792{
793 return bpf_prog_add(prog, 1);
794}
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700795
Daniel Borkmann113214b2016-06-30 17:24:44 +0200796static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700797{
798 struct fd f = fdget(ufd);
799 struct bpf_prog *prog;
800
Daniel Borkmann113214b2016-06-30 17:24:44 +0200801 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700802 if (IS_ERR(prog))
803 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200804 if (type && prog->type != *type) {
805 prog = ERR_PTR(-EINVAL);
806 goto out;
807 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700808
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700809 prog = bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +0200810out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700811 fdput(f);
812 return prog;
813}
Daniel Borkmann113214b2016-06-30 17:24:44 +0200814
815struct bpf_prog *bpf_prog_get(u32 ufd)
816{
817 return __bpf_prog_get(ufd, NULL);
818}
819
820struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
821{
822 return __bpf_prog_get(ufd, &type);
823}
824EXPORT_SYMBOL_GPL(bpf_prog_get_type);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700825
826/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov25415172015-03-25 12:49:20 -0700827#define BPF_PROG_LOAD_LAST_FIELD kern_version
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700828
829static int bpf_prog_load(union bpf_attr *attr)
830{
831 enum bpf_prog_type type = attr->prog_type;
832 struct bpf_prog *prog;
833 int err;
834 char license[128];
835 bool is_gpl;
836
837 if (CHECK_ATTR(BPF_PROG_LOAD))
838 return -EINVAL;
839
840 /* copy eBPF program license from user space */
841 if (strncpy_from_user(license, u64_to_ptr(attr->license),
842 sizeof(license) - 1) < 0)
843 return -EFAULT;
844 license[sizeof(license) - 1] = 0;
845
846 /* eBPF programs must be GPL compatible to use GPL-ed functions */
847 is_gpl = license_is_gpl_compatible(license);
848
849 if (attr->insn_cnt >= BPF_MAXINSNS)
850 return -EINVAL;
851
Alexei Starovoitov25415172015-03-25 12:49:20 -0700852 if (type == BPF_PROG_TYPE_KPROBE &&
853 attr->kern_version != LINUX_VERSION_CODE)
854 return -EINVAL;
855
Chenbo Fengb9aad972017-06-02 17:24:31 -0700856 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
857 type != BPF_PROG_TYPE_CGROUP_SKB &&
858 !capable(CAP_SYS_ADMIN))
Alexei Starovoitov1be7f752015-10-07 22:23:21 -0700859 return -EPERM;
860
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700861 /* plain bpf_prog allocation */
862 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
863 if (!prog)
864 return -ENOMEM;
865
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700866 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700867 if (err)
868 goto free_prog_nouncharge;
869
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700870 err = bpf_prog_charge_memlock(prog);
871 if (err)
872 goto free_prog_sec;
873
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700874 prog->len = attr->insn_cnt;
875
876 err = -EFAULT;
877 if (copy_from_user(prog->insns, u64_to_ptr(attr->insns),
878 prog->len * sizeof(struct bpf_insn)) != 0)
879 goto free_prog;
880
881 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200882 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700883
884 atomic_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200885 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700886
887 /* find program type: socket_filter vs tracing_filter */
888 err = find_prog_type(type, prog);
889 if (err < 0)
890 goto free_prog;
891
892 /* run eBPF verifier */
Alexei Starovoitov9bac3d62015-03-13 11:57:42 -0700893 err = bpf_check(&prog, attr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700894 if (err < 0)
895 goto free_used_maps;
896
Alexei Starovoitov0a542a82014-09-26 00:17:01 -0700897 /* fixup BPF_CALL->imm field */
898 fixup_bpf_calls(prog);
899
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700900 /* eBPF program is ready to be JITed */
Daniel Borkmannd1c55ab2016-05-13 19:08:31 +0200901 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61a2015-05-19 16:59:03 -0700902 if (err < 0)
903 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700904
Daniel Borkmannaa797812015-10-29 14:58:06 +0100905 err = bpf_prog_new_fd(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700906 if (err < 0)
907 /* failed to allocate fd */
908 goto free_used_maps;
909
910 return err;
911
912free_used_maps:
913 free_used_maps(prog->aux);
914free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700915 bpf_prog_uncharge_memlock(prog);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700916free_prog_sec:
917 security_bpf_prog_free(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700918free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700919 bpf_prog_free(prog);
920 return err;
921}
922
Chenbo Feng4672ded2017-10-18 13:00:22 -0700923#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +0100924
925static int bpf_obj_pin(const union bpf_attr *attr)
926{
Chenbo Feng4672ded2017-10-18 13:00:22 -0700927 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +0100928 return -EINVAL;
929
930 return bpf_obj_pin_user(attr->bpf_fd, u64_to_ptr(attr->pathname));
931}
932
933static int bpf_obj_get(const union bpf_attr *attr)
934{
Chenbo Feng4672ded2017-10-18 13:00:22 -0700935 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
936 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +0100937 return -EINVAL;
938
Chenbo Feng4672ded2017-10-18 13:00:22 -0700939 return bpf_obj_get_user(u64_to_ptr(attr->pathname),
940 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +0100941}
942
Daniel Mack00615df2016-11-23 16:52:27 +0100943#ifdef CONFIG_CGROUP_BPF
944
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800945#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
Daniel Mack00615df2016-11-23 16:52:27 +0100946
947static int bpf_prog_attach(const union bpf_attr *attr)
948{
949 struct bpf_prog *prog;
950 struct cgroup *cgrp;
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800951 int ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100952
953 if (!capable(CAP_NET_ADMIN))
954 return -EPERM;
955
956 if (CHECK_ATTR(BPF_PROG_ATTACH))
957 return -EINVAL;
958
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800959 if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE)
960 return -EINVAL;
961
Daniel Mack00615df2016-11-23 16:52:27 +0100962 switch (attr->attach_type) {
963 case BPF_CGROUP_INET_INGRESS:
964 case BPF_CGROUP_INET_EGRESS:
965 prog = bpf_prog_get_type(attr->attach_bpf_fd,
966 BPF_PROG_TYPE_CGROUP_SKB);
967 if (IS_ERR(prog))
968 return PTR_ERR(prog);
969
970 cgrp = cgroup_get_from_fd(attr->target_fd);
971 if (IS_ERR(cgrp)) {
972 bpf_prog_put(prog);
973 return PTR_ERR(cgrp);
974 }
975
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800976 ret = cgroup_bpf_update(cgrp, prog, attr->attach_type,
977 attr->attach_flags & BPF_F_ALLOW_OVERRIDE);
978 if (ret)
979 bpf_prog_put(prog);
Daniel Mack00615df2016-11-23 16:52:27 +0100980 cgroup_put(cgrp);
981 break;
982
983 default:
984 return -EINVAL;
985 }
986
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800987 return ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100988}
989
990#define BPF_PROG_DETACH_LAST_FIELD attach_type
991
992static int bpf_prog_detach(const union bpf_attr *attr)
993{
994 struct cgroup *cgrp;
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800995 int ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100996
997 if (!capable(CAP_NET_ADMIN))
998 return -EPERM;
999
1000 if (CHECK_ATTR(BPF_PROG_DETACH))
1001 return -EINVAL;
1002
1003 switch (attr->attach_type) {
1004 case BPF_CGROUP_INET_INGRESS:
1005 case BPF_CGROUP_INET_EGRESS:
1006 cgrp = cgroup_get_from_fd(attr->target_fd);
1007 if (IS_ERR(cgrp))
1008 return PTR_ERR(cgrp);
1009
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -08001010 ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
Daniel Mack00615df2016-11-23 16:52:27 +01001011 cgroup_put(cgrp);
1012 break;
1013
1014 default:
1015 return -EINVAL;
1016 }
1017
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -08001018 return ret;
Daniel Mack00615df2016-11-23 16:52:27 +01001019}
1020#endif /* CONFIG_CGROUP_BPF */
1021
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001022SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
1023{
1024 union bpf_attr attr = {};
1025 int err;
1026
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07001027 if (!capable(CAP_SYS_ADMIN) && sysctl_unprivileged_bpf_disabled)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001028 return -EPERM;
1029
1030 if (!access_ok(VERIFY_READ, uattr, 1))
1031 return -EFAULT;
1032
1033 if (size > PAGE_SIZE) /* silly large */
1034 return -E2BIG;
1035
1036 /* If we're handed a bigger struct than we know of,
1037 * ensure all the unknown bits are 0 - i.e. new
1038 * user-space does not rely on any kernel feature
1039 * extensions we dont know about yet.
1040 */
1041 if (size > sizeof(attr)) {
1042 unsigned char __user *addr;
1043 unsigned char __user *end;
1044 unsigned char val;
1045
1046 addr = (void __user *)uattr + sizeof(attr);
1047 end = (void __user *)uattr + size;
1048
1049 for (; addr < end; addr++) {
1050 err = get_user(val, addr);
1051 if (err)
1052 return err;
1053 if (val)
1054 return -E2BIG;
1055 }
1056 size = sizeof(attr);
1057 }
1058
1059 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
1060 if (copy_from_user(&attr, uattr, size) != 0)
1061 return -EFAULT;
1062
Chenbo Fengf3ad3762017-10-18 13:00:24 -07001063 err = security_bpf(cmd, &attr, size);
1064 if (err < 0)
1065 return err;
1066
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001067 switch (cmd) {
1068 case BPF_MAP_CREATE:
1069 err = map_create(&attr);
1070 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001071 case BPF_MAP_LOOKUP_ELEM:
1072 err = map_lookup_elem(&attr);
1073 break;
1074 case BPF_MAP_UPDATE_ELEM:
1075 err = map_update_elem(&attr);
1076 break;
1077 case BPF_MAP_DELETE_ELEM:
1078 err = map_delete_elem(&attr);
1079 break;
1080 case BPF_MAP_GET_NEXT_KEY:
1081 err = map_get_next_key(&attr);
1082 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001083 case BPF_PROG_LOAD:
1084 err = bpf_prog_load(&attr);
1085 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01001086 case BPF_OBJ_PIN:
1087 err = bpf_obj_pin(&attr);
1088 break;
1089 case BPF_OBJ_GET:
1090 err = bpf_obj_get(&attr);
1091 break;
Daniel Mack00615df2016-11-23 16:52:27 +01001092
1093#ifdef CONFIG_CGROUP_BPF
1094 case BPF_PROG_ATTACH:
1095 err = bpf_prog_attach(&attr);
1096 break;
1097 case BPF_PROG_DETACH:
1098 err = bpf_prog_detach(&attr);
1099 break;
1100#endif
1101
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001102 default:
1103 err = -EINVAL;
1104 break;
1105 }
1106
1107 return err;
1108}