BPF List
 help / color / mirror / Atom feed
From: Yonghong Song <yhs@fb.com>
To: <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>, <kernel-team@fb.com>
Subject: [PATCH bpf-next v2 08/18] libbpf: Add enum64 sanitization
Date: Fri, 13 May 2022 20:13:03 -0700	[thread overview]
Message-ID: <20220514031303.3243922-1-yhs@fb.com> (raw)
In-Reply-To: <20220514031221.3240268-1-yhs@fb.com>

When old kernel does not support enum64 but user space btf
contains non-zero enum kflag or enum64, libbpf needs to
do proper sanitization so modified btf can be accepted
by the kernel.

Sanitization for enum kflag can be achieved by clearing
the kflag bit. For enum64, the type is replaced with an
union of integer member types and the integer member size
must be smaller than enum64 size. If such an integer
type cannot be found, a new type is created and used
for union members.

Signed-off-by: Yonghong Song <yhs@fb.com>
---
 tools/lib/bpf/btf.h             |  3 +-
 tools/lib/bpf/libbpf.c          | 53 +++++++++++++++++++++++++++++++--
 tools/lib/bpf/libbpf_internal.h |  2 ++
 3 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 7da6970b8c9f..d4fe1300ed33 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -395,9 +395,10 @@ btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
 #ifndef BTF_KIND_FLOAT
 #define BTF_KIND_FLOAT		16	/* Floating point	*/
 #endif
-/* The kernel header switched to enums, so these two were never #defined */
+/* The kernel header switched to enums, so the following were never #defined */
 #define BTF_KIND_DECL_TAG	17	/* Decl Tag */
 #define BTF_KIND_TYPE_TAG	18	/* Type Tag */
+#define BTF_KIND_ENUM64		19	/* Enum for up-to 64bit values */
 
 static inline __u16 btf_kind(const struct btf_type *t)
 {
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 4867a930628b..f54e70b9953d 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2114,6 +2114,7 @@ static const char *__btf_kind_str(__u16 kind)
 	case BTF_KIND_FLOAT: return "float";
 	case BTF_KIND_DECL_TAG: return "decl_tag";
 	case BTF_KIND_TYPE_TAG: return "type_tag";
+	case BTF_KIND_ENUM64: return "enum64";
 	default: return "unknown";
 	}
 }
@@ -2642,9 +2643,10 @@ static bool btf_needs_sanitization(struct bpf_object *obj)
 	bool has_func = kernel_supports(obj, FEAT_BTF_FUNC);
 	bool has_decl_tag = kernel_supports(obj, FEAT_BTF_DECL_TAG);
 	bool has_type_tag = kernel_supports(obj, FEAT_BTF_TYPE_TAG);
+	bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
 
 	return !has_func || !has_datasec || !has_func_global || !has_float ||
-	       !has_decl_tag || !has_type_tag;
+	       !has_decl_tag || !has_type_tag || !has_enum64;
 }
 
 static void bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *btf)
@@ -2655,9 +2657,25 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *btf)
 	bool has_func = kernel_supports(obj, FEAT_BTF_FUNC);
 	bool has_decl_tag = kernel_supports(obj, FEAT_BTF_DECL_TAG);
 	bool has_type_tag = kernel_supports(obj, FEAT_BTF_TYPE_TAG);
+	bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
+	int min_int_size = 32, min_enum64_size = 32, min_int_tid = 0;
 	struct btf_type *t;
 	int i, j, vlen;
 
+	if (!has_enum64) {
+		for (i = 1; i < btf__type_cnt(btf); i++) {
+			t = (struct btf_type *)btf__type_by_id(btf, i);
+			if (btf_is_int(t) && t->size < min_int_size) {
+				min_int_size = t->size;
+				min_int_tid = i;
+			} else if (btf_is_enum64(t) && t->size < min_enum64_size) {
+				min_enum64_size = t->size;
+			}
+		}
+		if (min_int_size > min_enum64_size)
+			min_int_tid = btf__add_int(btf, "char", 1,  BTF_INT_SIGNED);
+	}
+
 	for (i = 1; i < btf__type_cnt(btf); i++) {
 		t = (struct btf_type *)btf__type_by_id(btf, i);
 
@@ -2717,7 +2735,20 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *btf)
 			/* replace TYPE_TAG with a CONST */
 			t->name_off = 0;
 			t->info = BTF_INFO_ENC(BTF_KIND_CONST, 0, 0);
-		}
+		} else if (!has_enum64 && btf_is_enum(t)) {
+			/* clear the kflag */
+			t->info = btf_type_info(btf_kind(t), btf_vlen(t), false);
+		} else if (!has_enum64 && btf_is_enum64(t)) {
+			/* replace ENUM64 with a union */
+			struct btf_member *m = btf_members(t);
+
+			vlen = btf_vlen(t);
+			t->info = BTF_INFO_ENC(BTF_KIND_UNION, 0, vlen);
+			for (j = 0; j < vlen; j++, m++) {
+				m->type = min_int_tid;
+				m->offset = 0;
+			}
+                }
 	}
 }
 
@@ -3563,6 +3594,10 @@ static enum kcfg_type find_kcfg_type(const struct btf *btf, int id,
 		if (strcmp(name, "libbpf_tristate"))
 			return KCFG_UNKNOWN;
 		return KCFG_TRISTATE;
+	case BTF_KIND_ENUM64:
+		if (strcmp(name, "libbpf_tristate"))
+			return KCFG_UNKNOWN;
+		return KCFG_TRISTATE;
 	case BTF_KIND_ARRAY:
 		if (btf_array(t)->nelems == 0)
 			return KCFG_UNKNOWN;
@@ -4746,6 +4781,17 @@ static int probe_kern_bpf_cookie(void)
 	return probe_fd(ret);
 }
 
+static int probe_kern_btf_enum64(void)
+{
+	static const char strs[] = "\0enum64";
+	__u32 types[] = {
+		BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_ENUM64, 0, 0), 8),
+	};
+
+	return probe_fd(libbpf__load_raw_btf((char *)types, sizeof(types),
+					     strs, sizeof(strs)));
+}
+
 enum kern_feature_result {
 	FEAT_UNKNOWN = 0,
 	FEAT_SUPPORTED = 1,
@@ -4811,6 +4857,9 @@ static struct kern_feature_desc {
 	[FEAT_BPF_COOKIE] = {
 		"BPF cookie support", probe_kern_bpf_cookie,
 	},
+	[FEAT_BTF_ENUM64] = {
+		"BTF_KIND_ENUM64 support", probe_kern_btf_enum64,
+	},
 };
 
 bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 4abdbe2fea9d..10c16acfa8ae 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -351,6 +351,8 @@ enum kern_feature_id {
 	FEAT_MEMCG_ACCOUNT,
 	/* BPF cookie (bpf_get_attach_cookie() BPF helper) support */
 	FEAT_BPF_COOKIE,
+	/* BTF_KIND_ENUM64 support and BTF_KIND_ENUM kflag support */
+	FEAT_BTF_ENUM64,
 	__FEAT_CNT,
 };
 
-- 
2.30.2


  parent reply	other threads:[~2022-05-14  3:13 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-14  3:12 [PATCH bpf-next v2 00/18] bpf: Add 64bit enum value support Yonghong Song
2022-05-14  3:12 ` [PATCH bpf-next v2 01/18] bpf: Add btf enum64 support Yonghong Song
2022-05-17  0:06   ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 02/18] libbpf: Permit 64bit relocation value Yonghong Song
2022-05-17  0:08   ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 03/18] libbpf: Fix an error in 64bit relocation value computation Yonghong Song
2022-05-17  0:10   ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 04/18] libbpf: Refactor btf__add_enum() for future code sharing Yonghong Song
2022-05-17  0:15   ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 05/18] libbpf: Add enum64 parsing and new enum64 public API Yonghong Song
2022-05-17  0:15   ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 06/18] libbpf: Add enum64 deduplication support Yonghong Song
2022-05-17  0:28   ` Andrii Nakryiko
2022-05-17 17:11     ` Yonghong Song
2022-05-17 22:22       ` Andrii Nakryiko
2022-05-14  3:12 ` [PATCH bpf-next v2 07/18] libbpf: Add enum64 support for btf_dump Yonghong Song
2022-05-17  0:37   ` Andrii Nakryiko
2022-05-17 17:15     ` Yonghong Song
2022-05-14  3:13 ` Yonghong Song [this message]
2022-05-17 23:25   ` [PATCH bpf-next v2 08/18] libbpf: Add enum64 sanitization Andrii Nakryiko
2022-05-18 21:08     ` Yonghong Song
2022-05-14  3:13 ` [PATCH bpf-next v2 09/18] libbpf: Add enum64 support for bpf linking Yonghong Song
2022-05-17 23:25   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 10/18] libbpf: Add enum64 relocation support Yonghong Song
2022-05-17 23:32   ` Andrii Nakryiko
2022-05-18 21:09     ` Yonghong Song
2022-05-14  3:13 ` [PATCH bpf-next v2 11/18] bpftool: Add btf enum64 support Yonghong Song
2022-05-17 23:38   ` Andrii Nakryiko
2022-05-18 21:10     ` Yonghong Song
2022-05-14  3:13 ` [PATCH bpf-next v2 12/18] selftests/bpf: Fix selftests failure Yonghong Song
2022-05-17 23:33   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 13/18] selftests/bpf: Test new enum kflag and enum64 API functions Yonghong Song
2022-05-17 23:40   ` Andrii Nakryiko
2022-05-18 21:12     ` Yonghong Song
2022-05-14  3:13 ` [PATCH bpf-next v2 14/18] selftests/bpf: Add BTF_KIND_ENUM64 unit tests Yonghong Song
2022-05-17 23:41   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 15/18] selftests/bpf: Test BTF_KIND_ENUM64 for deduplication Yonghong Song
2022-05-17 23:43   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 16/18] selftests/bpf: Add a test for enum64 value relocations Yonghong Song
2022-05-17 23:45   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 17/18] selftests/bpf: Clarify llvm dependency with possible selftest failures Yonghong Song
2022-05-17 23:45   ` Andrii Nakryiko
2022-05-14  3:13 ` [PATCH bpf-next v2 18/18] docs/bpf: Update documentation for BTF_KIND_ENUM64 support Yonghong Song
2022-05-17 23:47   ` Andrii Nakryiko
2022-05-18 21:21     ` Yonghong Song

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=20220514031303.3243922-1-yhs@fb.com \
    --to=yhs@fb.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@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