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