summaryrefslogtreecommitdiffstats
path: root/tools/testing
diff options
context:
space:
mode:
authorAlan Maguire <alan.maguire@oracle.com>2026-04-08 17:57:35 +0100
committerAlexei Starovoitov <ast@kernel.org>2026-04-10 12:34:36 -0700
commit0e4dc6fbddb01b2ce0d0b4d67ad5f70e976bedcc (patch)
treea1b5aa828eba7f5964aa1d0882d0e6fd0ec60ebc /tools/testing
parent7419fcadd1dcd5efb5771a2725f9a80dc90d9e5a (diff)
downloadlinux-0e4dc6fbddb01b2ce0d0b4d67ad5f70e976bedcc.tar.gz
linux-0e4dc6fbddb01b2ce0d0b4d67ad5f70e976bedcc.zip
selftests/bpf: Add BTF sanitize test covering BTF layout
Add test that fakes up a feature cache of supported BPF features to simulate an older kernel that does not support BTF layout information. Ensure that BTF is sanitized correctly to remove layout info between types and strings, and that all offsets and lengths are adjusted appropriately. Signed-off-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/r/20260408165735.843763-3-alan.maguire@oracle.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/prog_tests/btf_sanitize.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
new file mode 100644
index 000000000000..652b51efafc2
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026, Oracle and/or its affiliates. */
+#include <test_progs.h>
+#include <linux/btf.h>
+#include "bpf/libbpf_internal.h"
+#include "../test_btf.h"
+#include "kfree_skb.skel.h"
+
+#define TYPE_LEN (sizeof(struct btf_type) + sizeof(__u32))
+#define MAX_NR_LAYOUT 2
+#define LAYOUT_LEN (sizeof(struct btf_layout) * MAX_NR_LAYOUT)
+#define STR_LEN sizeof("\0int")
+
+struct layout_btf {
+ struct btf_header hdr;
+ __u32 types[TYPE_LEN/sizeof(__u32)];
+ struct btf_layout layout[MAX_NR_LAYOUT];
+ char strs[STR_LEN];
+};
+
+static const struct layout_btf layout_btf = {
+ .hdr = {
+ .magic = BTF_MAGIC,
+ .version = BTF_VERSION,
+ .hdr_len = sizeof(struct btf_header),
+ .type_off = 0,
+ .type_len = TYPE_LEN,
+ .str_off = TYPE_LEN + LAYOUT_LEN,
+ .str_len = STR_LEN,
+ .layout_off = TYPE_LEN,
+ .layout_len = LAYOUT_LEN,
+ },
+ .types = {
+ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
+ },
+ .layout = {
+ { .info_sz = 0, .elem_sz = 0, .flags = 0 },
+ { .info_sz = sizeof(__u32), .elem_sz = 0, .flags = 0 },
+ },
+ .strs = "\0int",
+};
+
+void test_btf_sanitize_layout(void)
+{
+ struct btf *orig = NULL, *sanitized = NULL;
+ struct kern_feature_cache *cache = NULL;
+ struct kfree_skb *skel = NULL;
+ const struct btf_header *hdr;
+ const void *raw;
+ __u32 raw_sz;
+
+ skel = kfree_skb__open();
+ if (!ASSERT_OK_PTR(skel, "kfree_skb_skel"))
+ return;
+ orig = btf__new(&layout_btf, sizeof(layout_btf));
+ if (!ASSERT_OK_PTR(orig, "btf_new_layout"))
+ goto out;
+ raw = btf__raw_data(orig, &raw_sz);
+ if (!ASSERT_OK_PTR(raw, "btf__raw_data_orig"))
+ goto out;
+ hdr = (struct btf_header *)raw;
+ ASSERT_EQ(hdr->layout_off, TYPE_LEN, "layout_off_nonzero");
+ ASSERT_EQ(hdr->layout_len, LAYOUT_LEN, "layout_len_nonzero");
+
+ cache = calloc(1, sizeof(*cache));
+ if (!ASSERT_OK_PTR(cache, "alloc_feat_cache"))
+ goto out;
+ for (int i = 0; i < __FEAT_CNT; i++)
+ cache->res[i] = FEAT_SUPPORTED;
+ cache->res[FEAT_BTF_LAYOUT] = FEAT_MISSING;
+
+ bpf_object_set_feat_cache(skel->obj, cache);
+
+ if (!ASSERT_FALSE(kernel_supports(skel->obj, FEAT_BTF_LAYOUT), "layout_feature_missing"))
+ goto out;
+ if (!ASSERT_TRUE(kernel_supports(skel->obj, FEAT_BTF_FUNC), "other_feature_allowed"))
+ goto out;
+
+ sanitized = bpf_object__sanitize_btf(skel->obj, orig);
+ if (!ASSERT_OK_PTR(sanitized, "bpf_object__sanitize_btf"))
+ goto out;
+
+ raw = btf__raw_data(sanitized, &raw_sz);
+ if (!ASSERT_OK_PTR(raw, "btf__raw_data_sanitized"))
+ goto out;
+ hdr = (struct btf_header *)raw;
+ ASSERT_EQ(hdr->layout_off, 0, "layout_off_zero");
+ ASSERT_EQ(hdr->layout_len, 0, "layout_len_zero");
+ ASSERT_EQ(hdr->str_off, TYPE_LEN, "strs_after_types");
+ ASSERT_EQ(hdr->str_len, STR_LEN, "strs_len_unchanged");
+ ASSERT_EQ(raw_sz, hdr->hdr_len + hdr->type_len + hdr->str_len, "btf_raw_sz_reduced");
+out:
+ /* This will free the cache we allocated above */
+ kfree_skb__destroy(skel);
+ btf__free(sanitized);
+ btf__free(orig);
+}