1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Facebook */ 3 4 #include <test_progs.h> 5 #include <bpf/btf.h> 6 7 /* real layout and sizes according to test's (32-bit) BTF 8 * needs to be defined before skeleton is included */ 9 struct test_struct___real { 10 unsigned int ptr; /* can't use `void *`, it is always 8 byte in BPF target */ 11 unsigned int val2; 12 unsigned long long val1; 13 unsigned short val3; 14 unsigned char val4; 15 unsigned char _pad; 16 }; 17 18 #include "test_core_autosize.skel.h" 19 20 static int duration = 0; 21 22 static struct { 23 unsigned long long ptr_samesized; 24 unsigned long long val1_samesized; 25 unsigned long long val2_samesized; 26 unsigned long long val3_samesized; 27 unsigned long long val4_samesized; 28 struct test_struct___real output_samesized; 29 30 unsigned long long ptr_downsized; 31 unsigned long long val1_downsized; 32 unsigned long long val2_downsized; 33 unsigned long long val3_downsized; 34 unsigned long long val4_downsized; 35 struct test_struct___real output_downsized; 36 37 unsigned long long ptr_probed; 38 unsigned long long val1_probed; 39 unsigned long long val2_probed; 40 unsigned long long val3_probed; 41 unsigned long long val4_probed; 42 43 unsigned long long ptr_signed; 44 unsigned long long val1_signed; 45 unsigned long long val2_signed; 46 unsigned long long val3_signed; 47 unsigned long long val4_signed; 48 struct test_struct___real output_signed; 49 } out; 50 51 void test_core_autosize(void) 52 { 53 char btf_file[] = "/tmp/core_autosize.btf.XXXXXX"; 54 int err, fd = -1, zero = 0; 55 int char_id, short_id, int_id, long_long_id, void_ptr_id, id; 56 struct test_core_autosize* skel = NULL; 57 struct bpf_object_load_attr load_attr = {}; 58 struct bpf_program *prog; 59 struct bpf_map *bss_map; 60 struct btf *btf = NULL; 61 size_t written; 62 const void *raw_data; 63 __u32 raw_sz; 64 FILE *f = NULL; 65 66 btf = btf__new_empty(); 67 if (!ASSERT_OK_PTR(btf, "empty_btf")) 68 return; 69 /* Emit the following struct with 32-bit pointer size: 70 * 71 * struct test_struct { 72 * void *ptr; 73 * unsigned long val2; 74 * unsigned long long val1; 75 * unsigned short val3; 76 * unsigned char val4; 77 * char: 8; 78 * }; 79 * 80 * This struct is going to be used as the "kernel BTF" for this test. 81 * It's equivalent memory-layout-wise to test_struct__real above. 82 */ 83 84 /* force 32-bit pointer size */ 85 btf__set_pointer_size(btf, 4); 86 87 char_id = btf__add_int(btf, "unsigned char", 1, 0); 88 ASSERT_EQ(char_id, 1, "char_id"); 89 short_id = btf__add_int(btf, "unsigned short", 2, 0); 90 ASSERT_EQ(short_id, 2, "short_id"); 91 /* "long unsigned int" of 4 byte size tells BTF that sizeof(void *) == 4 */ 92 int_id = btf__add_int(btf, "long unsigned int", 4, 0); 93 ASSERT_EQ(int_id, 3, "int_id"); 94 long_long_id = btf__add_int(btf, "unsigned long long", 8, 0); 95 ASSERT_EQ(long_long_id, 4, "long_long_id"); 96 void_ptr_id = btf__add_ptr(btf, 0); 97 ASSERT_EQ(void_ptr_id, 5, "void_ptr_id"); 98 99 id = btf__add_struct(btf, "test_struct", 20 /* bytes */); 100 ASSERT_EQ(id, 6, "struct_id"); 101 err = btf__add_field(btf, "ptr", void_ptr_id, 0, 0); 102 err = err ?: btf__add_field(btf, "val2", int_id, 32, 0); 103 err = err ?: btf__add_field(btf, "val1", long_long_id, 64, 0); 104 err = err ?: btf__add_field(btf, "val3", short_id, 128, 0); 105 err = err ?: btf__add_field(btf, "val4", char_id, 144, 0); 106 ASSERT_OK(err, "struct_fields"); 107 108 fd = mkstemp(btf_file); 109 if (CHECK(fd < 0, "btf_tmp", "failed to create file: %d\n", fd)) 110 goto cleanup; 111 f = fdopen(fd, "w"); 112 if (!ASSERT_OK_PTR(f, "btf_fdopen")) 113 goto cleanup; 114 115 raw_data = btf__get_raw_data(btf, &raw_sz); 116 if (!ASSERT_OK_PTR(raw_data, "raw_data")) 117 goto cleanup; 118 written = fwrite(raw_data, 1, raw_sz, f); 119 if (CHECK(written != raw_sz, "btf_write", "written: %zu, errno: %d\n", written, errno)) 120 goto cleanup; 121 fflush(f); 122 fclose(f); 123 f = NULL; 124 close(fd); 125 fd = -1; 126 127 /* open and load BPF program with custom BTF as the kernel BTF */ 128 skel = test_core_autosize__open(); 129 if (!ASSERT_OK_PTR(skel, "skel_open")) 130 return; 131 132 /* disable handle_signed() for now */ 133 prog = bpf_object__find_program_by_name(skel->obj, "handle_signed"); 134 if (!ASSERT_OK_PTR(prog, "prog_find")) 135 goto cleanup; 136 bpf_program__set_autoload(prog, false); 137 138 load_attr.obj = skel->obj; 139 load_attr.target_btf_path = btf_file; 140 err = bpf_object__load_xattr(&load_attr); 141 if (!ASSERT_OK(err, "prog_load")) 142 goto cleanup; 143 144 prog = bpf_object__find_program_by_name(skel->obj, "handle_samesize"); 145 if (!ASSERT_OK_PTR(prog, "prog_find")) 146 goto cleanup; 147 skel->links.handle_samesize = bpf_program__attach(prog); 148 if (!ASSERT_OK_PTR(skel->links.handle_samesize, "prog_attach")) 149 goto cleanup; 150 151 prog = bpf_object__find_program_by_name(skel->obj, "handle_downsize"); 152 if (!ASSERT_OK_PTR(prog, "prog_find")) 153 goto cleanup; 154 skel->links.handle_downsize = bpf_program__attach(prog); 155 if (!ASSERT_OK_PTR(skel->links.handle_downsize, "prog_attach")) 156 goto cleanup; 157 158 prog = bpf_object__find_program_by_name(skel->obj, "handle_probed"); 159 if (!ASSERT_OK_PTR(prog, "prog_find")) 160 goto cleanup; 161 skel->links.handle_probed = bpf_program__attach(prog); 162 if (!ASSERT_OK_PTR(skel->links.handle_probed, "prog_attach")) 163 goto cleanup; 164 165 usleep(1); 166 167 bss_map = bpf_object__find_map_by_name(skel->obj, "test_cor.bss"); 168 if (!ASSERT_OK_PTR(bss_map, "bss_map_find")) 169 goto cleanup; 170 171 err = bpf_map_lookup_elem(bpf_map__fd(bss_map), &zero, (void *)&out); 172 if (!ASSERT_OK(err, "bss_lookup")) 173 goto cleanup; 174 175 ASSERT_EQ(out.ptr_samesized, 0x01020304, "ptr_samesized"); 176 ASSERT_EQ(out.val1_samesized, 0x1020304050607080, "val1_samesized"); 177 ASSERT_EQ(out.val2_samesized, 0x0a0b0c0d, "val2_samesized"); 178 ASSERT_EQ(out.val3_samesized, 0xfeed, "val3_samesized"); 179 ASSERT_EQ(out.val4_samesized, 0xb9, "val4_samesized"); 180 ASSERT_EQ(out.output_samesized.ptr, 0x01020304, "ptr_samesized"); 181 ASSERT_EQ(out.output_samesized.val1, 0x1020304050607080, "val1_samesized"); 182 ASSERT_EQ(out.output_samesized.val2, 0x0a0b0c0d, "val2_samesized"); 183 ASSERT_EQ(out.output_samesized.val3, 0xfeed, "val3_samesized"); 184 ASSERT_EQ(out.output_samesized.val4, 0xb9, "val4_samesized"); 185 186 ASSERT_EQ(out.ptr_downsized, 0x01020304, "ptr_downsized"); 187 ASSERT_EQ(out.val1_downsized, 0x1020304050607080, "val1_downsized"); 188 ASSERT_EQ(out.val2_downsized, 0x0a0b0c0d, "val2_downsized"); 189 ASSERT_EQ(out.val3_downsized, 0xfeed, "val3_downsized"); 190 ASSERT_EQ(out.val4_downsized, 0xb9, "val4_downsized"); 191 ASSERT_EQ(out.output_downsized.ptr, 0x01020304, "ptr_downsized"); 192 ASSERT_EQ(out.output_downsized.val1, 0x1020304050607080, "val1_downsized"); 193 ASSERT_EQ(out.output_downsized.val2, 0x0a0b0c0d, "val2_downsized"); 194 ASSERT_EQ(out.output_downsized.val3, 0xfeed, "val3_downsized"); 195 ASSERT_EQ(out.output_downsized.val4, 0xb9, "val4_downsized"); 196 197 ASSERT_EQ(out.ptr_probed, 0x01020304, "ptr_probed"); 198 ASSERT_EQ(out.val1_probed, 0x1020304050607080, "val1_probed"); 199 ASSERT_EQ(out.val2_probed, 0x0a0b0c0d, "val2_probed"); 200 ASSERT_EQ(out.val3_probed, 0xfeed, "val3_probed"); 201 ASSERT_EQ(out.val4_probed, 0xb9, "val4_probed"); 202 203 test_core_autosize__destroy(skel); 204 skel = NULL; 205 206 /* now re-load with handle_signed() enabled, it should fail loading */ 207 skel = test_core_autosize__open(); 208 if (!ASSERT_OK_PTR(skel, "skel_open")) 209 return; 210 211 load_attr.obj = skel->obj; 212 load_attr.target_btf_path = btf_file; 213 err = bpf_object__load_xattr(&load_attr); 214 if (!ASSERT_ERR(err, "bad_prog_load")) 215 goto cleanup; 216 217 cleanup: 218 if (f) 219 fclose(f); 220 if (fd >= 0) 221 close(fd); 222 remove(btf_file); 223 btf__free(btf); 224 test_core_autosize__destroy(skel); 225 } 226