diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-08-11 19:59:17 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-08-12 18:52:45 -0400 |
commit | e8d2bec0457962e8f348a9a3627b398f7fe5c5fc (patch) | |
tree | 9bda920c6a2940980aeb18a79b827b11e3f1cb0d /kernel/bpf/syscall.c | |
parent | 9d6f417714c3aaf67b23ffdc1d2b036cce3ecc1c (diff) |
bpf: decouple btf from seq bpf fs dump and enable more maps
Commit a26ca7c982cb ("bpf: btf: Add pretty print support to
the basic arraymap") and 699c86d6ec21 ("bpf: btf: add pretty
print for hash/lru_hash maps") enabled support for BTF and
dumping via BPF fs for array and hash/lru map. However, both
can be decoupled from each other such that regular BPF maps
can be supported for attaching BTF key/value information,
while not all maps necessarily need to dump via map_seq_show_elem()
callback.
The basic sanity check which is a prerequisite for all maps
is that key/value size has to match in any case, and some maps
can have extra checks via map_check_btf() callback, e.g.
probing certain types or indicating no support in general. With
that we can also enable retrieving BTF info for per-cpu map
types and lpm.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 57f4d076141b..43727ed0d94a 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -103,6 +103,7 @@ int bpf_check_uarg_tail_zero(void __user *uaddr, | |||
103 | const struct bpf_map_ops bpf_map_offload_ops = { | 103 | const struct bpf_map_ops bpf_map_offload_ops = { |
104 | .map_alloc = bpf_map_offload_map_alloc, | 104 | .map_alloc = bpf_map_offload_map_alloc, |
105 | .map_free = bpf_map_offload_map_free, | 105 | .map_free = bpf_map_offload_map_free, |
106 | .map_check_btf = map_check_no_btf, | ||
106 | }; | 107 | }; |
107 | 108 | ||
108 | static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) | 109 | static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) |
@@ -455,6 +456,34 @@ static int bpf_obj_name_cpy(char *dst, const char *src) | |||
455 | return 0; | 456 | return 0; |
456 | } | 457 | } |
457 | 458 | ||
459 | int map_check_no_btf(const struct bpf_map *map, | ||
460 | const struct btf_type *key_type, | ||
461 | const struct btf_type *value_type) | ||
462 | { | ||
463 | return -ENOTSUPP; | ||
464 | } | ||
465 | |||
466 | static int map_check_btf(const struct bpf_map *map, const struct btf *btf, | ||
467 | u32 btf_key_id, u32 btf_value_id) | ||
468 | { | ||
469 | const struct btf_type *key_type, *value_type; | ||
470 | u32 key_size, value_size; | ||
471 | int ret = 0; | ||
472 | |||
473 | key_type = btf_type_id_size(btf, &btf_key_id, &key_size); | ||
474 | if (!key_type || key_size != map->key_size) | ||
475 | return -EINVAL; | ||
476 | |||
477 | value_type = btf_type_id_size(btf, &btf_value_id, &value_size); | ||
478 | if (!value_type || value_size != map->value_size) | ||
479 | return -EINVAL; | ||
480 | |||
481 | if (map->ops->map_check_btf) | ||
482 | ret = map->ops->map_check_btf(map, key_type, value_type); | ||
483 | |||
484 | return ret; | ||
485 | } | ||
486 | |||
458 | #define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id | 487 | #define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id |
459 | /* called via syscall */ | 488 | /* called via syscall */ |
460 | static int map_create(union bpf_attr *attr) | 489 | static int map_create(union bpf_attr *attr) |
@@ -489,8 +518,7 @@ static int map_create(union bpf_attr *attr) | |||
489 | atomic_set(&map->refcnt, 1); | 518 | atomic_set(&map->refcnt, 1); |
490 | atomic_set(&map->usercnt, 1); | 519 | atomic_set(&map->usercnt, 1); |
491 | 520 | ||
492 | if (bpf_map_support_seq_show(map) && | 521 | if (attr->btf_key_type_id || attr->btf_value_type_id) { |
493 | (attr->btf_key_type_id || attr->btf_value_type_id)) { | ||
494 | struct btf *btf; | 522 | struct btf *btf; |
495 | 523 | ||
496 | if (!attr->btf_key_type_id || !attr->btf_value_type_id) { | 524 | if (!attr->btf_key_type_id || !attr->btf_value_type_id) { |
@@ -504,8 +532,8 @@ static int map_create(union bpf_attr *attr) | |||
504 | goto free_map_nouncharge; | 532 | goto free_map_nouncharge; |
505 | } | 533 | } |
506 | 534 | ||
507 | err = map->ops->map_check_btf(map, btf, attr->btf_key_type_id, | 535 | err = map_check_btf(map, btf, attr->btf_key_type_id, |
508 | attr->btf_value_type_id); | 536 | attr->btf_value_type_id); |
509 | if (err) { | 537 | if (err) { |
510 | btf_put(btf); | 538 | btf_put(btf); |
511 | goto free_map_nouncharge; | 539 | goto free_map_nouncharge; |