blob: c92cf06f3515c31c094a7b331d92b87428a8be20 [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
Chenbo Feng0521e0b2017-10-18 13:00:26 -0700202const 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
Teng Qinfcbc8d02017-04-24 19:00:37 -0700582 if (ukey) {
583 err = -ENOMEM;
584 key = kmalloc(map->key_size, GFP_USER);
585 if (!key)
586 goto err_put;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700587
Teng Qinfcbc8d02017-04-24 19:00:37 -0700588 err = -EFAULT;
589 if (copy_from_user(key, ukey, map->key_size) != 0)
590 goto free_key;
591 } else {
592 key = NULL;
593 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700594
595 err = -ENOMEM;
596 next_key = kmalloc(map->key_size, GFP_USER);
597 if (!next_key)
598 goto free_key;
599
600 rcu_read_lock();
601 err = map->ops->map_get_next_key(map, key, next_key);
602 rcu_read_unlock();
603 if (err)
604 goto free_next_key;
605
606 err = -EFAULT;
607 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
608 goto free_next_key;
609
610 err = 0;
611
612free_next_key:
613 kfree(next_key);
614free_key:
615 kfree(key);
616err_put:
617 fdput(f);
618 return err;
619}
620
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700621static LIST_HEAD(bpf_prog_types);
622
623static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
624{
625 struct bpf_prog_type_list *tl;
626
627 list_for_each_entry(tl, &bpf_prog_types, list_node) {
628 if (tl->type == type) {
629 prog->aux->ops = tl->ops;
Daniel Borkmann24701ec2015-03-01 12:31:47 +0100630 prog->type = type;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700631 return 0;
632 }
633 }
Daniel Borkmann24701ec2015-03-01 12:31:47 +0100634
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700635 return -EINVAL;
636}
637
638void bpf_register_prog_type(struct bpf_prog_type_list *tl)
639{
640 list_add(&tl->list_node, &bpf_prog_types);
641}
642
643/* drop refcnt on maps used by eBPF program and free auxilary data */
644static void free_used_maps(struct bpf_prog_aux *aux)
645{
646 int i;
647
648 for (i = 0; i < aux->used_map_cnt; i++)
649 bpf_map_put(aux->used_maps[i]);
650
651 kfree(aux->used_maps);
652}
653
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700654static int bpf_prog_charge_memlock(struct bpf_prog *prog)
655{
656 struct user_struct *user = get_current_user();
657 unsigned long memlock_limit;
658
659 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
660
661 atomic_long_add(prog->pages, &user->locked_vm);
662 if (atomic_long_read(&user->locked_vm) > memlock_limit) {
663 atomic_long_sub(prog->pages, &user->locked_vm);
664 free_uid(user);
665 return -EPERM;
666 }
667 prog->aux->user = user;
668 return 0;
669}
670
671static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
672{
673 struct user_struct *user = prog->aux->user;
674
675 atomic_long_sub(prog->pages, &user->locked_vm);
676 free_uid(user);
677}
678
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200679static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700680{
681 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
682
683 free_used_maps(aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700684 bpf_prog_uncharge_memlock(aux->prog);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700685 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -0700686 bpf_prog_free(aux->prog);
687}
688
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700689void bpf_prog_put(struct bpf_prog *prog)
690{
Daniel Borkmanne9d8afa2015-10-29 14:58:08 +0100691 if (atomic_dec_and_test(&prog->aux->refcnt))
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200692 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700693}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +0100694EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700695
696static int bpf_prog_release(struct inode *inode, struct file *filp)
697{
698 struct bpf_prog *prog = filp->private_data;
699
Daniel Borkmann1aacde32016-06-30 17:24:43 +0200700 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700701 return 0;
702}
703
Chenbo Feng0521e0b2017-10-18 13:00:26 -0700704const struct file_operations bpf_prog_fops = {
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700705 .release = bpf_prog_release,
Chenbo Feng4672ded2017-10-18 13:00:22 -0700706 .read = bpf_dummy_read,
707 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700708};
709
Daniel Borkmannb2197752015-10-29 14:58:09 +0100710int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100711{
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700712 int ret;
713
714 ret = security_bpf_prog(prog);
715 if (ret < 0)
716 return ret;
717
Daniel Borkmannaa797812015-10-29 14:58:06 +0100718 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
719 O_RDWR | O_CLOEXEC);
720}
721
Daniel Borkmann113214b2016-06-30 17:24:44 +0200722static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700723{
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700724 if (!f.file)
725 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700726 if (f.file->f_op != &bpf_prog_fops) {
727 fdput(f);
728 return ERR_PTR(-EINVAL);
729 }
730
Daniel Borkmannc2101292015-10-29 14:58:07 +0100731 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700732}
733
Brenden Blanco59d36562016-07-19 12:16:46 -0700734struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700735{
Brenden Blanco59d36562016-07-19 12:16:46 -0700736 if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
737 atomic_sub(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700738 return ERR_PTR(-EBUSY);
739 }
740 return prog;
741}
Brenden Blanco59d36562016-07-19 12:16:46 -0700742EXPORT_SYMBOL_GPL(bpf_prog_add);
743
744struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
745{
746 return bpf_prog_add(prog, 1);
747}
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700748
Daniel Borkmann113214b2016-06-30 17:24:44 +0200749static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *type)
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700750{
751 struct fd f = fdget(ufd);
752 struct bpf_prog *prog;
753
Daniel Borkmann113214b2016-06-30 17:24:44 +0200754 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700755 if (IS_ERR(prog))
756 return prog;
Daniel Borkmann113214b2016-06-30 17:24:44 +0200757 if (type && prog->type != *type) {
758 prog = ERR_PTR(-EINVAL);
759 goto out;
760 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700761
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700762 prog = bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +0200763out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700764 fdput(f);
765 return prog;
766}
Daniel Borkmann113214b2016-06-30 17:24:44 +0200767
768struct bpf_prog *bpf_prog_get(u32 ufd)
769{
770 return __bpf_prog_get(ufd, NULL);
771}
772
773struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
774{
775 return __bpf_prog_get(ufd, &type);
776}
777EXPORT_SYMBOL_GPL(bpf_prog_get_type);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700778
779/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov25415172015-03-25 12:49:20 -0700780#define BPF_PROG_LOAD_LAST_FIELD kern_version
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700781
782static int bpf_prog_load(union bpf_attr *attr)
783{
784 enum bpf_prog_type type = attr->prog_type;
785 struct bpf_prog *prog;
786 int err;
787 char license[128];
788 bool is_gpl;
789
790 if (CHECK_ATTR(BPF_PROG_LOAD))
791 return -EINVAL;
792
793 /* copy eBPF program license from user space */
794 if (strncpy_from_user(license, u64_to_ptr(attr->license),
795 sizeof(license) - 1) < 0)
796 return -EFAULT;
797 license[sizeof(license) - 1] = 0;
798
799 /* eBPF programs must be GPL compatible to use GPL-ed functions */
800 is_gpl = license_is_gpl_compatible(license);
801
802 if (attr->insn_cnt >= BPF_MAXINSNS)
803 return -EINVAL;
804
Alexei Starovoitov25415172015-03-25 12:49:20 -0700805 if (type == BPF_PROG_TYPE_KPROBE &&
806 attr->kern_version != LINUX_VERSION_CODE)
807 return -EINVAL;
808
Chenbo Fengb9aad972017-06-02 17:24:31 -0700809 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
810 type != BPF_PROG_TYPE_CGROUP_SKB &&
811 !capable(CAP_SYS_ADMIN))
Alexei Starovoitov1be7f752015-10-07 22:23:21 -0700812 return -EPERM;
813
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700814 /* plain bpf_prog allocation */
815 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
816 if (!prog)
817 return -ENOMEM;
818
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700819 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700820 if (err)
821 goto free_prog_nouncharge;
822
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700823 err = bpf_prog_charge_memlock(prog);
824 if (err)
825 goto free_prog_sec;
826
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700827 prog->len = attr->insn_cnt;
828
829 err = -EFAULT;
830 if (copy_from_user(prog->insns, u64_to_ptr(attr->insns),
831 prog->len * sizeof(struct bpf_insn)) != 0)
832 goto free_prog;
833
834 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200835 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700836
837 atomic_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +0200838 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700839
840 /* find program type: socket_filter vs tracing_filter */
841 err = find_prog_type(type, prog);
842 if (err < 0)
843 goto free_prog;
844
845 /* run eBPF verifier */
Alexei Starovoitov9bac3d62015-03-13 11:57:42 -0700846 err = bpf_check(&prog, attr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700847 if (err < 0)
848 goto free_used_maps;
849
850 /* eBPF program is ready to be JITed */
Daniel Borkmannd1c55ab2016-05-13 19:08:31 +0200851 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61a2015-05-19 16:59:03 -0700852 if (err < 0)
853 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700854
Daniel Borkmannaa797812015-10-29 14:58:06 +0100855 err = bpf_prog_new_fd(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700856 if (err < 0)
857 /* failed to allocate fd */
858 goto free_used_maps;
859
860 return err;
861
862free_used_maps:
863 free_used_maps(prog->aux);
864free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700865 bpf_prog_uncharge_memlock(prog);
Chenbo Fengf3ad3762017-10-18 13:00:24 -0700866free_prog_sec:
867 security_bpf_prog_free(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700868free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -0700869 bpf_prog_free(prog);
870 return err;
871}
872
Chenbo Feng4672ded2017-10-18 13:00:22 -0700873#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +0100874
875static int bpf_obj_pin(const union bpf_attr *attr)
876{
Chenbo Feng4672ded2017-10-18 13:00:22 -0700877 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +0100878 return -EINVAL;
879
880 return bpf_obj_pin_user(attr->bpf_fd, u64_to_ptr(attr->pathname));
881}
882
883static int bpf_obj_get(const union bpf_attr *attr)
884{
Chenbo Feng4672ded2017-10-18 13:00:22 -0700885 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
886 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +0100887 return -EINVAL;
888
Chenbo Feng4672ded2017-10-18 13:00:22 -0700889 return bpf_obj_get_user(u64_to_ptr(attr->pathname),
890 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +0100891}
892
Daniel Mack00615df2016-11-23 16:52:27 +0100893#ifdef CONFIG_CGROUP_BPF
894
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800895#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
Daniel Mack00615df2016-11-23 16:52:27 +0100896
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700897#define BPF_F_ATTACH_MASK \
898 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)
899
Daniel Mack00615df2016-11-23 16:52:27 +0100900static int bpf_prog_attach(const union bpf_attr *attr)
901{
902 struct bpf_prog *prog;
903 struct cgroup *cgrp;
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800904 int ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100905
906 if (!capable(CAP_NET_ADMIN))
907 return -EPERM;
908
909 if (CHECK_ATTR(BPF_PROG_ATTACH))
910 return -EINVAL;
911
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700912 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800913 return -EINVAL;
914
Daniel Mack00615df2016-11-23 16:52:27 +0100915 switch (attr->attach_type) {
916 case BPF_CGROUP_INET_INGRESS:
917 case BPF_CGROUP_INET_EGRESS:
918 prog = bpf_prog_get_type(attr->attach_bpf_fd,
919 BPF_PROG_TYPE_CGROUP_SKB);
920 if (IS_ERR(prog))
921 return PTR_ERR(prog);
922
923 cgrp = cgroup_get_from_fd(attr->target_fd);
924 if (IS_ERR(cgrp)) {
925 bpf_prog_put(prog);
926 return PTR_ERR(cgrp);
927 }
928
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700929 ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
930 attr->attach_flags);
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800931 if (ret)
932 bpf_prog_put(prog);
Daniel Mack00615df2016-11-23 16:52:27 +0100933 cgroup_put(cgrp);
934 break;
935
936 default:
937 return -EINVAL;
938 }
939
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800940 return ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100941}
942
943#define BPF_PROG_DETACH_LAST_FIELD attach_type
944
945static int bpf_prog_detach(const union bpf_attr *attr)
946{
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700947 enum bpf_prog_type ptype;
948 struct bpf_prog *prog;
Daniel Mack00615df2016-11-23 16:52:27 +0100949 struct cgroup *cgrp;
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800950 int ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100951
952 if (!capable(CAP_NET_ADMIN))
953 return -EPERM;
954
955 if (CHECK_ATTR(BPF_PROG_DETACH))
956 return -EINVAL;
957
958 switch (attr->attach_type) {
959 case BPF_CGROUP_INET_INGRESS:
960 case BPF_CGROUP_INET_EGRESS:
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700961 ptype = BPF_PROG_TYPE_CGROUP_SKB;
Daniel Mack00615df2016-11-23 16:52:27 +0100962 break;
963
964 default:
965 return -EINVAL;
966 }
967
Alexei Starovoitov148f1112017-10-02 22:50:21 -0700968 cgrp = cgroup_get_from_fd(attr->target_fd);
969 if (IS_ERR(cgrp))
970 return PTR_ERR(cgrp);
971
972 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
973 if (IS_ERR(prog))
974 prog = NULL;
975
976 ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
977 if (prog)
978 bpf_prog_put(prog);
979 cgroup_put(cgrp);
Alexei Starovoitov1ee2b4b2017-02-10 20:28:24 -0800980 return ret;
Daniel Mack00615df2016-11-23 16:52:27 +0100981}
982#endif /* CONFIG_CGROUP_BPF */
983
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700984SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
985{
Greg Kroah-Hartman2fc19cf2020-03-20 10:48:13 +0100986 union bpf_attr attr;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700987 int err;
988
Chenbo Feng3eb88802018-03-19 17:57:27 -0700989 if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN))
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700990 return -EPERM;
991
992 if (!access_ok(VERIFY_READ, uattr, 1))
993 return -EFAULT;
994
995 if (size > PAGE_SIZE) /* silly large */
996 return -E2BIG;
997
998 /* If we're handed a bigger struct than we know of,
999 * ensure all the unknown bits are 0 - i.e. new
1000 * user-space does not rely on any kernel feature
1001 * extensions we dont know about yet.
1002 */
1003 if (size > sizeof(attr)) {
1004 unsigned char __user *addr;
1005 unsigned char __user *end;
1006 unsigned char val;
1007
1008 addr = (void __user *)uattr + sizeof(attr);
1009 end = (void __user *)uattr + size;
1010
1011 for (; addr < end; addr++) {
1012 err = get_user(val, addr);
1013 if (err)
1014 return err;
1015 if (val)
1016 return -E2BIG;
1017 }
1018 size = sizeof(attr);
1019 }
1020
1021 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
Greg Kroah-Hartman2fc19cf2020-03-20 10:48:13 +01001022 memset(&attr, 0, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001023 if (copy_from_user(&attr, uattr, size) != 0)
1024 return -EFAULT;
1025
Chenbo Fengf3ad3762017-10-18 13:00:24 -07001026 err = security_bpf(cmd, &attr, size);
1027 if (err < 0)
1028 return err;
1029
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001030 switch (cmd) {
1031 case BPF_MAP_CREATE:
1032 err = map_create(&attr);
1033 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001034 case BPF_MAP_LOOKUP_ELEM:
1035 err = map_lookup_elem(&attr);
1036 break;
1037 case BPF_MAP_UPDATE_ELEM:
1038 err = map_update_elem(&attr);
1039 break;
1040 case BPF_MAP_DELETE_ELEM:
1041 err = map_delete_elem(&attr);
1042 break;
1043 case BPF_MAP_GET_NEXT_KEY:
1044 err = map_get_next_key(&attr);
1045 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001046 case BPF_PROG_LOAD:
1047 err = bpf_prog_load(&attr);
1048 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01001049 case BPF_OBJ_PIN:
1050 err = bpf_obj_pin(&attr);
1051 break;
1052 case BPF_OBJ_GET:
1053 err = bpf_obj_get(&attr);
1054 break;
Daniel Mack00615df2016-11-23 16:52:27 +01001055
1056#ifdef CONFIG_CGROUP_BPF
1057 case BPF_PROG_ATTACH:
1058 err = bpf_prog_attach(&attr);
1059 break;
1060 case BPF_PROG_DETACH:
1061 err = bpf_prog_detach(&attr);
1062 break;
1063#endif
1064
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001065 default:
1066 err = -EINVAL;
1067 break;
1068 }
1069
1070 return err;
1071}