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