All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Borkmann <daniel@iogearbox.net>
To: bpf@vger.kernel.org
Cc: netdev@vger.kernel.org, ast@kernel.org, joe@wand.net.nz,
	yhs@fb.com, andrii.nakryiko@gmail.com, kafai@fb.com,
	jannh@google.com, Daniel Borkmann <daniel@iogearbox.net>
Subject: [PATCH bpf-next v6 08/16] bpf: allow for key-less BTF in array map
Date: Tue,  9 Apr 2019 23:20:10 +0200	[thread overview]
Message-ID: <20190409212018.32423-9-daniel@iogearbox.net> (raw)
In-Reply-To: <20190409212018.32423-1-daniel@iogearbox.net>

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>
---
 include/linux/btf.h   |  1 +
 kernel/bpf/arraymap.c | 15 ++++++++++++++-
 kernel/bpf/btf.c      |  2 +-
 kernel/bpf/syscall.c  | 15 +++++++++++----
 4 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 455d31b55828..64cdf2a23d42 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -51,6 +51,7 @@ bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
 			   const struct btf_member *m,
 			   u32 expected_offset, u32 expected_size);
 int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t);
+bool btf_type_is_void(const struct btf_type *t);
 
 #ifdef CONFIG_BPF_SYSCALL
 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 217b10bd9f48..584636c9e2eb 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -391,7 +391,8 @@ static void array_map_seq_show_elem(struct bpf_map *map, void *key,
 		return;
 	}
 
-	seq_printf(m, "%u: ", *(u32 *)key);
+	if (map->btf_key_type_id)
+		seq_printf(m, "%u: ", *(u32 *)key);
 	btf_type_seq_show(map->btf, map->btf_value_type_id, value, m);
 	seq_puts(m, "\n");
 
@@ -428,6 +429,18 @@ static int array_map_check_btf(const struct bpf_map *map,
 {
 	u32 int_data;
 
+	/* One exception for keyless BTF: .bss/.data/.rodata map */
+	if (btf_type_is_void(key_type)) {
+		if (map->map_type != BPF_MAP_TYPE_ARRAY ||
+		    map->max_entries != 1)
+			return -EINVAL;
+
+		if (BTF_INFO_KIND(value_type->info) != BTF_KIND_DATASEC)
+			return -EINVAL;
+
+		return 0;
+	}
+
 	if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
 		return -EINVAL;
 
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 0cecf6bab61b..cad09858a5f2 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -326,7 +326,7 @@ static bool btf_type_is_modifier(const struct btf_type *t)
 	return false;
 }
 
-static bool btf_type_is_void(const struct btf_type *t)
+bool btf_type_is_void(const struct btf_type *t)
 {
 	return t == &btf_void;
 }
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,
 	u32 key_size, value_size;
 	int ret = 0;
 
-	key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
-	if (!key_type || key_size != map->key_size)
-		return -EINVAL;
+	/* Some maps allow key to be unspecified. */
+	if (btf_key_id) {
+		key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
+		if (!key_type || key_size != map->key_size)
+			return -EINVAL;
+	} else {
+		key_type = btf_type_by_id(btf, 0);
+		if (!map->ops->map_check_btf)
+			return -EINVAL;
+	}
 
 	value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
 	if (!value_type || value_size != map->value_size)
@@ -573,7 +580,7 @@ static int map_create(union bpf_attr *attr)
 	if (attr->btf_key_type_id || attr->btf_value_type_id) {
 		struct btf *btf;
 
-		if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
+		if (!attr->btf_value_type_id) {
 			err = -EINVAL;
 			goto free_map_nouncharge;
 		}
-- 
2.17.1


  parent reply	other threads:[~2019-04-09 21:21 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-09 21:20 [PATCH bpf-next v6 00/16] BPF support for global data Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 01/16] bpf: implement lookup-free direct value access for maps Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 02/16] bpf: do not retain flags that are not tied to map lifetime Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 03/16] bpf: add program side {rd, wr}only support for maps Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 04/16] bpf: add syscall side map freeze support Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 05/16] bpf: allow . char as part of the object name Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 06/16] bpf: add specification for BTF Var and DataSec kinds Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 07/16] bpf: kernel side support for BTF Var and DataSec Daniel Borkmann
2019-04-09 21:20 ` Daniel Borkmann [this message]
2019-04-09 21:20 ` [PATCH bpf-next v6 09/16] bpf: sync {btf, bpf}.h uapi header from tools infrastructure Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 10/16] bpf, libbpf: refactor relocation handling Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 11/16] bpf, libbpf: support global data/bss/rodata sections Daniel Borkmann
2019-04-19  1:18   ` Andrii Nakryiko
2019-04-23  0:35     ` Daniel Borkmann
2019-04-23  4:06       ` Andrii Nakryiko
2019-04-23  8:31         ` Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 12/16] bpf, libbpf: add support for BTF Var and DataSec Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 13/16] bpf: bpftool support for dumping data/bss/rodata sections Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 14/16] bpf, selftest: test {rd, wr}only flags and direct value access Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 15/16] bpf, selftest: test global data/bss/rodata sections Daniel Borkmann
2019-04-09 21:20 ` [PATCH bpf-next v6 16/16] bpf, selftest: add test cases for BTF Var and DataSec Daniel Borkmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190409212018.32423-9-daniel@iogearbox.net \
    --to=daniel@iogearbox.net \
    --cc=andrii.nakryiko@gmail.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=jannh@google.com \
    --cc=joe@wand.net.nz \
    --cc=kafai@fb.com \
    --cc=netdev@vger.kernel.org \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.