xref: /linux/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1*0e4dc6fbSAlan Maguire // SPDX-License-Identifier: GPL-2.0
2*0e4dc6fbSAlan Maguire /* Copyright (c) 2026, Oracle and/or its affiliates. */
3*0e4dc6fbSAlan Maguire #include <test_progs.h>
4*0e4dc6fbSAlan Maguire #include <linux/btf.h>
5*0e4dc6fbSAlan Maguire #include "bpf/libbpf_internal.h"
6*0e4dc6fbSAlan Maguire #include "../test_btf.h"
7*0e4dc6fbSAlan Maguire #include "kfree_skb.skel.h"
8*0e4dc6fbSAlan Maguire 
9*0e4dc6fbSAlan Maguire #define TYPE_LEN	(sizeof(struct btf_type) + sizeof(__u32))
10*0e4dc6fbSAlan Maguire #define MAX_NR_LAYOUT	2
11*0e4dc6fbSAlan Maguire #define LAYOUT_LEN	(sizeof(struct btf_layout) * MAX_NR_LAYOUT)
12*0e4dc6fbSAlan Maguire #define STR_LEN		sizeof("\0int")
13*0e4dc6fbSAlan Maguire 
14*0e4dc6fbSAlan Maguire struct layout_btf {
15*0e4dc6fbSAlan Maguire 	struct btf_header hdr;
16*0e4dc6fbSAlan Maguire 	__u32 types[TYPE_LEN/sizeof(__u32)];
17*0e4dc6fbSAlan Maguire 	struct btf_layout layout[MAX_NR_LAYOUT];
18*0e4dc6fbSAlan Maguire 	char strs[STR_LEN];
19*0e4dc6fbSAlan Maguire };
20*0e4dc6fbSAlan Maguire 
21*0e4dc6fbSAlan Maguire static const struct layout_btf layout_btf = {
22*0e4dc6fbSAlan Maguire 	.hdr = {
23*0e4dc6fbSAlan Maguire 		.magic		= BTF_MAGIC,
24*0e4dc6fbSAlan Maguire 		.version	= BTF_VERSION,
25*0e4dc6fbSAlan Maguire 		.hdr_len	= sizeof(struct btf_header),
26*0e4dc6fbSAlan Maguire 		.type_off	= 0,
27*0e4dc6fbSAlan Maguire 		.type_len	= TYPE_LEN,
28*0e4dc6fbSAlan Maguire 		.str_off	= TYPE_LEN + LAYOUT_LEN,
29*0e4dc6fbSAlan Maguire 		.str_len	= STR_LEN,
30*0e4dc6fbSAlan Maguire 		.layout_off	= TYPE_LEN,
31*0e4dc6fbSAlan Maguire 		.layout_len	= LAYOUT_LEN,
32*0e4dc6fbSAlan Maguire 	},
33*0e4dc6fbSAlan Maguire 	.types = {
34*0e4dc6fbSAlan Maguire 		BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
35*0e4dc6fbSAlan Maguire 	},
36*0e4dc6fbSAlan Maguire 	.layout = {
37*0e4dc6fbSAlan Maguire 		{ .info_sz = 0,          .elem_sz = 0, .flags = 0 },
38*0e4dc6fbSAlan Maguire 		{ .info_sz = sizeof(__u32), .elem_sz = 0, .flags = 0 },
39*0e4dc6fbSAlan Maguire 	},
40*0e4dc6fbSAlan Maguire 	.strs = "\0int",
41*0e4dc6fbSAlan Maguire };
42*0e4dc6fbSAlan Maguire 
43*0e4dc6fbSAlan Maguire void test_btf_sanitize_layout(void)
44*0e4dc6fbSAlan Maguire {
45*0e4dc6fbSAlan Maguire 	struct btf *orig = NULL, *sanitized = NULL;
46*0e4dc6fbSAlan Maguire 	struct kern_feature_cache *cache = NULL;
47*0e4dc6fbSAlan Maguire 	struct kfree_skb *skel = NULL;
48*0e4dc6fbSAlan Maguire 	const struct btf_header *hdr;
49*0e4dc6fbSAlan Maguire 	const void *raw;
50*0e4dc6fbSAlan Maguire 	__u32 raw_sz;
51*0e4dc6fbSAlan Maguire 
52*0e4dc6fbSAlan Maguire 	skel = kfree_skb__open();
53*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(skel, "kfree_skb_skel"))
54*0e4dc6fbSAlan Maguire 		return;
55*0e4dc6fbSAlan Maguire 	orig = btf__new(&layout_btf, sizeof(layout_btf));
56*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(orig, "btf_new_layout"))
57*0e4dc6fbSAlan Maguire 		goto out;
58*0e4dc6fbSAlan Maguire 	raw = btf__raw_data(orig, &raw_sz);
59*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(raw, "btf__raw_data_orig"))
60*0e4dc6fbSAlan Maguire 		goto out;
61*0e4dc6fbSAlan Maguire 	hdr = (struct btf_header *)raw;
62*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->layout_off, TYPE_LEN, "layout_off_nonzero");
63*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->layout_len, LAYOUT_LEN, "layout_len_nonzero");
64*0e4dc6fbSAlan Maguire 
65*0e4dc6fbSAlan Maguire 	cache = calloc(1, sizeof(*cache));
66*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(cache, "alloc_feat_cache"))
67*0e4dc6fbSAlan Maguire 		goto out;
68*0e4dc6fbSAlan Maguire 	for (int i = 0; i < __FEAT_CNT; i++)
69*0e4dc6fbSAlan Maguire 		cache->res[i] = FEAT_SUPPORTED;
70*0e4dc6fbSAlan Maguire 	cache->res[FEAT_BTF_LAYOUT] = FEAT_MISSING;
71*0e4dc6fbSAlan Maguire 
72*0e4dc6fbSAlan Maguire 	bpf_object_set_feat_cache(skel->obj, cache);
73*0e4dc6fbSAlan Maguire 
74*0e4dc6fbSAlan Maguire 	if (!ASSERT_FALSE(kernel_supports(skel->obj, FEAT_BTF_LAYOUT), "layout_feature_missing"))
75*0e4dc6fbSAlan Maguire 		goto out;
76*0e4dc6fbSAlan Maguire 	if (!ASSERT_TRUE(kernel_supports(skel->obj, FEAT_BTF_FUNC), "other_feature_allowed"))
77*0e4dc6fbSAlan Maguire 		goto out;
78*0e4dc6fbSAlan Maguire 
79*0e4dc6fbSAlan Maguire 	sanitized = bpf_object__sanitize_btf(skel->obj, orig);
80*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(sanitized, "bpf_object__sanitize_btf"))
81*0e4dc6fbSAlan Maguire 		goto out;
82*0e4dc6fbSAlan Maguire 
83*0e4dc6fbSAlan Maguire 	raw = btf__raw_data(sanitized, &raw_sz);
84*0e4dc6fbSAlan Maguire 	if (!ASSERT_OK_PTR(raw, "btf__raw_data_sanitized"))
85*0e4dc6fbSAlan Maguire 		goto out;
86*0e4dc6fbSAlan Maguire 	hdr = (struct btf_header *)raw;
87*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->layout_off, 0, "layout_off_zero");
88*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->layout_len, 0, "layout_len_zero");
89*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->str_off, TYPE_LEN, "strs_after_types");
90*0e4dc6fbSAlan Maguire 	ASSERT_EQ(hdr->str_len, STR_LEN, "strs_len_unchanged");
91*0e4dc6fbSAlan Maguire 	ASSERT_EQ(raw_sz, hdr->hdr_len + hdr->type_len + hdr->str_len, "btf_raw_sz_reduced");
92*0e4dc6fbSAlan Maguire out:
93*0e4dc6fbSAlan Maguire 	/* This will free the cache we allocated above */
94*0e4dc6fbSAlan Maguire 	kfree_skb__destroy(skel);
95*0e4dc6fbSAlan Maguire 	btf__free(sanitized);
96*0e4dc6fbSAlan Maguire 	btf__free(orig);
97*0e4dc6fbSAlan Maguire }
98