BPF List
 help / color / mirror / Atom feed
From: Alan Maguire <alan.maguire@oracle.com>
To: andrii@kernel.org, ast@kernel.org, daniel@iogearbox.net
Cc: martin.lau@linux.dev, song@kernel.org, yhs@fb.com,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com,
	haoluo@google.com, jolsa@kernel.org, mykolal@fb.com,
	haiyue.wang@intel.com, bpf@vger.kernel.org,
	Alan Maguire <alan.maguire@oracle.com>
Subject: [RFC bpf-next 4/5] bpf: parse unrecognized kind info using encoded kind information (if present)
Date: Wed, 23 Nov 2022 17:41:51 +0000	[thread overview]
Message-ID: <1669225312-28949-5-git-send-email-alan.maguire@oracle.com> (raw)
In-Reply-To: <1669225312-28949-1-git-send-email-alan.maguire@oracle.com>

When BTF parsing encounters an unrecognized kind (> BTF_KIND_MAX), look
for __BTF_KIND_<num> typedef which points at the associated kind struct;
it tells us if there is metadata and how much.  This all allows us to
proceed with BTF parsing rather than bailing when hitting a kind we
do not support.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
 kernel/bpf/btf.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 80 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 1a59cc7..ce00a4c5 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -222,6 +222,14 @@ struct btf_id_dtor_kfunc_tab {
 	struct btf_id_dtor_kfunc dtors[];
 };
 
+struct btf_kind_desc {
+	u16 kind;
+	u16 nr_meta;
+	u32 meta_size;
+};
+
+#define NR_BTF_KINDS_POSSIBLE	0x20
+
 struct btf {
 	void *data;
 	struct btf_type **types;
@@ -246,6 +254,7 @@ struct btf {
 	u32 start_str_off; /* first string offset (0 for base BTF) */
 	char name[MODULE_NAME_LEN];
 	bool kernel_btf;
+	struct btf_kind_desc unrecognized_kinds[NR_BTF_KINDS_POSSIBLE - NR_BTF_KINDS];
 };
 
 enum verifier_phase {
@@ -4873,7 +4882,7 @@ static s32 btf_check_meta(struct btf_verifier_env *env,
 			  u32 meta_left)
 {
 	u32 saved_meta_left = meta_left;
-	s32 var_meta_size;
+	s32 var_meta_size = 0;
 
 	if (meta_left < sizeof(*t)) {
 		btf_verifier_log(env, "[%u] meta_left:%u meta_needed:%zu",
@@ -4888,12 +4897,80 @@ static s32 btf_check_meta(struct btf_verifier_env *env,
 		return -EINVAL;
 	}
 
-	if (BTF_INFO_KIND(t->info) > BTF_KIND_MAX ||
-	    BTF_INFO_KIND(t->info) == BTF_KIND_UNKN) {
+	if (BTF_INFO_KIND(t->info) == BTF_KIND_UNKN ||
+	    BTF_INFO_KIND(t->info) >= NR_BTF_KINDS_POSSIBLE) {
 		btf_verifier_log(env, "[%u] Invalid kind:%u",
 				 env->log_type_id, BTF_INFO_KIND(t->info));
 		return -EINVAL;
 	}
+	if (BTF_INFO_KIND(t->info) <= BTF_KIND_MAX) {
+		var_meta_size = btf_type_ops(t)->check_meta(env, t, meta_left);
+		if (var_meta_size < 0)
+			return var_meta_size;
+	} else {
+		struct btf_kind_desc *unrec_kind;
+		u8 kind = BTF_INFO_KIND(t->info);
+		struct btf *btf = env->btf;
+
+		unrec_kind = &btf->unrecognized_kinds[kind - NR_BTF_KINDS];
+
+		if (unrec_kind->kind != kind) {
+			const struct btf_member *m;
+			const struct btf_type *kt;
+			const struct btf_array *a;
+			char name[64];
+			s32 id;
+
+			/* BTF may encode info about unrecognized kinds; check for this here. */
+			snprintf(name, sizeof(name), BTF_KIND_PFX "%u", kind);
+			id = btf_find_by_name_kind(btf, name, BTF_KIND_TYPEDEF);
+			if (id > 0) {
+				kt = btf_type_by_id(btf, id);
+				if (kt)
+					kt = btf_type_by_id(btf, kt->type);
+			}
+			if (id < 0 || !kt) {
+				btf_verifier_log_type(env, t, "[%u] invalid kind:%u",
+						      env->log_type_id, kind);
+				return -EINVAL;
+			}
+			switch (btf_type_vlen(kt)) {
+			case 1:
+				/* no metadata */
+				unrec_kind->kind = kind;
+				unrec_kind->nr_meta = 0;
+				unrec_kind->meta_size = 0;
+				break;
+			case 2:
+				m = btf_members(kt);
+				kt = btf_type_by_id(btf, (++m)->type);
+				if (btf_kind(kt) != BTF_KIND_ARRAY) {
+					btf_verifier_log_type(env, t, "[%u] invalid metadata:%u",
+							      env->log_type_id, kind);
+					return -EINVAL;
+				}
+				a = btf_array(kt);
+				kt = btf_type_by_id(btf, a->type);
+				if (!kt) {
+					btf_verifier_log_type(env, t, "[%u] invalid metadata:%u",
+							      env->log_type_id, kind);
+					return -EINVAL;
+				}
+				unrec_kind->kind = kind;
+				unrec_kind->nr_meta = a->nelems;
+				unrec_kind->meta_size = kt->size;
+				break;
+			default:
+				btf_verifier_log_type(env, t, "[%u] invalid metadata:%u",
+						      env->log_type_id, kind);
+				return -EINVAL;
+			}
+		}
+		if (!unrec_kind->nr_meta)
+			var_meta_size = btf_type_vlen(t) * unrec_kind->meta_size;
+		else
+			var_meta_size = unrec_kind->nr_meta * unrec_kind->meta_size;
+	}
 
 	if (!btf_name_offset_valid(env->btf, t->name_off)) {
 		btf_verifier_log(env, "[%u] Invalid name_offset:%u",
@@ -4901,10 +4978,6 @@ static s32 btf_check_meta(struct btf_verifier_env *env,
 		return -EINVAL;
 	}
 
-	var_meta_size = btf_type_ops(t)->check_meta(env, t, meta_left);
-	if (var_meta_size < 0)
-		return var_meta_size;
-
 	meta_left -= var_meta_size;
 
 	return saved_meta_left - meta_left;
-- 
1.8.3.1


  parent reply	other threads:[~2022-11-23 17:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-23 17:41 [RFC bpf-next 0/5] bpf: making BTF self-describing Alan Maguire
2022-11-23 17:41 ` [RFC bpf-next 1/5] bpf: add kind/metadata prefixes to uapi/linux/btf.h Alan Maguire
2022-11-23 17:41 ` [RFC bpf-next 2/5] libbpf: provide libbpf API to encode BTF kind information Alan Maguire
2022-11-29  5:35   ` Andrii Nakryiko
2022-11-29 13:51     ` Alan Maguire
2022-11-29 17:01       ` Andrii Nakryiko
2022-11-30 22:34         ` Alan Maguire
2022-12-02 23:43           ` Andrii Nakryiko
2022-11-23 17:41 ` [RFC bpf-next 3/5] libbpf: use BTF-encoded kind information to help parse unrecognized kinds Alan Maguire
2022-11-23 17:41 ` Alan Maguire [this message]
2022-11-23 17:41 ` [RFC bpf-next 5/5] selftests/bpf: test kind encoding/decoding Alan Maguire

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=1669225312-28949-5-git-send-email-alan.maguire@oracle.com \
    --to=alan.maguire@oracle.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=haiyue.wang@intel.com \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=mykolal@fb.com \
    --cc=sdf@google.com \
    --cc=song@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox