diff options
Diffstat (limited to 'kernel/bpf/arraymap.c')
| -rw-r--r-- | kernel/bpf/arraymap.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 172dc8ee0e3b..d771a3872500 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c | |||
| @@ -335,6 +335,26 @@ static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key) | |||
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | /* only called from syscall */ | 337 | /* only called from syscall */ |
| 338 | int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value) | ||
| 339 | { | ||
| 340 | void **elem, *ptr; | ||
| 341 | int ret = 0; | ||
| 342 | |||
| 343 | if (!map->ops->map_fd_sys_lookup_elem) | ||
| 344 | return -ENOTSUPP; | ||
| 345 | |||
| 346 | rcu_read_lock(); | ||
| 347 | elem = array_map_lookup_elem(map, key); | ||
| 348 | if (elem && (ptr = READ_ONCE(*elem))) | ||
| 349 | *value = map->ops->map_fd_sys_lookup_elem(ptr); | ||
| 350 | else | ||
| 351 | ret = -ENOENT; | ||
| 352 | rcu_read_unlock(); | ||
| 353 | |||
| 354 | return ret; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* only called from syscall */ | ||
| 338 | int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, | 358 | int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, |
| 339 | void *key, void *value, u64 map_flags) | 359 | void *key, void *value, u64 map_flags) |
| 340 | { | 360 | { |
| @@ -400,6 +420,11 @@ static void prog_fd_array_put_ptr(void *ptr) | |||
| 400 | bpf_prog_put(ptr); | 420 | bpf_prog_put(ptr); |
| 401 | } | 421 | } |
| 402 | 422 | ||
| 423 | static u32 prog_fd_array_sys_lookup_elem(void *ptr) | ||
| 424 | { | ||
| 425 | return ((struct bpf_prog *)ptr)->aux->id; | ||
| 426 | } | ||
| 427 | |||
| 403 | /* decrement refcnt of all bpf_progs that are stored in this map */ | 428 | /* decrement refcnt of all bpf_progs that are stored in this map */ |
| 404 | void bpf_fd_array_map_clear(struct bpf_map *map) | 429 | void bpf_fd_array_map_clear(struct bpf_map *map) |
| 405 | { | 430 | { |
| @@ -418,6 +443,7 @@ const struct bpf_map_ops prog_array_map_ops = { | |||
| 418 | .map_delete_elem = fd_array_map_delete_elem, | 443 | .map_delete_elem = fd_array_map_delete_elem, |
| 419 | .map_fd_get_ptr = prog_fd_array_get_ptr, | 444 | .map_fd_get_ptr = prog_fd_array_get_ptr, |
| 420 | .map_fd_put_ptr = prog_fd_array_put_ptr, | 445 | .map_fd_put_ptr = prog_fd_array_put_ptr, |
| 446 | .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem, | ||
| 421 | }; | 447 | }; |
| 422 | 448 | ||
| 423 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, | 449 | static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, |
| @@ -452,38 +478,24 @@ static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee) | |||
| 452 | static void *perf_event_fd_array_get_ptr(struct bpf_map *map, | 478 | static void *perf_event_fd_array_get_ptr(struct bpf_map *map, |
| 453 | struct file *map_file, int fd) | 479 | struct file *map_file, int fd) |
| 454 | { | 480 | { |
| 455 | const struct perf_event_attr *attr; | ||
| 456 | struct bpf_event_entry *ee; | 481 | struct bpf_event_entry *ee; |
| 457 | struct perf_event *event; | 482 | struct perf_event *event; |
| 458 | struct file *perf_file; | 483 | struct file *perf_file; |
| 484 | u64 value; | ||
| 459 | 485 | ||
| 460 | perf_file = perf_event_get(fd); | 486 | perf_file = perf_event_get(fd); |
| 461 | if (IS_ERR(perf_file)) | 487 | if (IS_ERR(perf_file)) |
| 462 | return perf_file; | 488 | return perf_file; |
| 463 | 489 | ||
| 490 | ee = ERR_PTR(-EOPNOTSUPP); | ||
| 464 | event = perf_file->private_data; | 491 | event = perf_file->private_data; |
| 465 | ee = ERR_PTR(-EINVAL); | 492 | if (perf_event_read_local(event, &value) == -EOPNOTSUPP) |
| 466 | |||
| 467 | attr = perf_event_attrs(event); | ||
| 468 | if (IS_ERR(attr) || attr->inherit) | ||
| 469 | goto err_out; | 493 | goto err_out; |
| 470 | 494 | ||
| 471 | switch (attr->type) { | 495 | ee = bpf_event_entry_gen(perf_file, map_file); |
| 472 | case PERF_TYPE_SOFTWARE: | 496 | if (ee) |
| 473 | if (attr->config != PERF_COUNT_SW_BPF_OUTPUT) | 497 | return ee; |
| 474 | goto err_out; | 498 | ee = ERR_PTR(-ENOMEM); |
| 475 | /* fall-through */ | ||
| 476 | case PERF_TYPE_RAW: | ||
| 477 | case PERF_TYPE_HARDWARE: | ||
| 478 | ee = bpf_event_entry_gen(perf_file, map_file); | ||
| 479 | if (ee) | ||
| 480 | return ee; | ||
| 481 | ee = ERR_PTR(-ENOMEM); | ||
| 482 | /* fall-through */ | ||
| 483 | default: | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | |||
| 487 | err_out: | 499 | err_out: |
| 488 | fput(perf_file); | 500 | fput(perf_file); |
| 489 | return ee; | 501 | return ee; |
| @@ -599,4 +611,5 @@ const struct bpf_map_ops array_of_maps_map_ops = { | |||
| 599 | .map_delete_elem = fd_array_map_delete_elem, | 611 | .map_delete_elem = fd_array_map_delete_elem, |
| 600 | .map_fd_get_ptr = bpf_map_fd_get_ptr, | 612 | .map_fd_get_ptr = bpf_map_fd_get_ptr, |
| 601 | .map_fd_put_ptr = bpf_map_fd_put_ptr, | 613 | .map_fd_put_ptr = bpf_map_fd_put_ptr, |
| 614 | .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem, | ||
| 602 | }; | 615 | }; |
