summaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-04-09 17:20:10 -0400
committerAlexei Starovoitov <ast@kernel.org>2019-04-09 20:05:46 -0400
commit2824ecb7010f6a20e9a4140512b798469ab066cc (patch)
treebb72402c12f3dd2f34be1d12e460442e7ed79b54 /kernel/bpf/syscall.c
parent1dc92851849cc2235a1efef8f8d5a9255efc5f13 (diff)
bpf: allow for key-less BTF in array map
Given we'll be reusing BPF array maps for global data/bss/rodata sections, we need a way to associate BTF DataSec type as its map value type. In usual cases we have this ugly BPF_ANNOTATE_KV_PAIR() macro hack e.g. via 38d5d3b3d5db ("bpf: Introduce BPF_ANNOTATE_KV_PAIR") to get initial map to type association going. While more use cases for it are discouraged, this also won't work for global data since the use of array map is a BPF loader detail and therefore unknown at compilation time. For array maps with just a single entry we make an exception in terms of BTF in that key type is declared optional if value type is of DataSec type. The latter LLVM is guaranteed to emit and it also aligns with how we regard global data maps as just a plain buffer area reusing existing map facilities for allowing things like introspection with existing tools. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 198c9680bf0d..438199e2eca4 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -504,9 +504,16 @@ static int map_check_btf(struct bpf_map *map, const struct btf *btf,
504 u32 key_size, value_size; 504 u32 key_size, value_size;
505 int ret = 0; 505 int ret = 0;
506 506
507 key_type = btf_type_id_size(btf, &btf_key_id, &key_size); 507 /* Some maps allow key to be unspecified. */
508 if (!key_type || key_size != map->key_size) 508 if (btf_key_id) {
509 return -EINVAL; 509 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
510 if (!key_type || key_size != map->key_size)
511 return -EINVAL;
512 } else {
513 key_type = btf_type_by_id(btf, 0);
514 if (!map->ops->map_check_btf)
515 return -EINVAL;
516 }
510 517
511 value_type = btf_type_id_size(btf, &btf_value_id, &value_size); 518 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
512 if (!value_type || value_size != map->value_size) 519 if (!value_type || value_size != map->value_size)
@@ -573,7 +580,7 @@ static int map_create(union bpf_attr *attr)
573 if (attr->btf_key_type_id || attr->btf_value_type_id) { 580 if (attr->btf_key_type_id || attr->btf_value_type_id) {
574 struct btf *btf; 581 struct btf *btf;
575 582
576 if (!attr->btf_key_type_id || !attr->btf_value_type_id) { 583 if (!attr->btf_value_type_id) {
577 err = -EINVAL; 584 err = -EINVAL;
578 goto free_map_nouncharge; 585 goto free_map_nouncharge;
579 } 586 }