1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 4 static void test_global_data_number(struct bpf_object *obj, __u32 duration) 5 { 6 int i, err, map_fd; 7 uint64_t num; 8 9 map_fd = bpf_find_map(__func__, obj, "result_number"); 10 if (map_fd < 0) { 11 error_cnt++; 12 return; 13 } 14 15 struct { 16 char *name; 17 uint32_t key; 18 uint64_t num; 19 } tests[] = { 20 { "relocate .bss reference", 0, 0 }, 21 { "relocate .data reference", 1, 42 }, 22 { "relocate .rodata reference", 2, 24 }, 23 { "relocate .bss reference", 3, 0 }, 24 { "relocate .data reference", 4, 0xffeeff }, 25 { "relocate .rodata reference", 5, 0xabab }, 26 { "relocate .bss reference", 6, 1234 }, 27 { "relocate .bss reference", 7, 0 }, 28 { "relocate .rodata reference", 8, 0xab }, 29 { "relocate .rodata reference", 9, 0x1111111111111111 }, 30 { "relocate .rodata reference", 10, ~0 }, 31 }; 32 33 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 34 err = bpf_map_lookup_elem(map_fd, &tests[i].key, &num); 35 CHECK(err || num != tests[i].num, tests[i].name, 36 "err %d result %lx expected %lx\n", 37 err, num, tests[i].num); 38 } 39 } 40 41 static void test_global_data_string(struct bpf_object *obj, __u32 duration) 42 { 43 int i, err, map_fd; 44 char str[32]; 45 46 map_fd = bpf_find_map(__func__, obj, "result_string"); 47 if (map_fd < 0) { 48 error_cnt++; 49 return; 50 } 51 52 struct { 53 char *name; 54 uint32_t key; 55 char str[32]; 56 } tests[] = { 57 { "relocate .rodata reference", 0, "abcdefghijklmnopqrstuvwxyz" }, 58 { "relocate .data reference", 1, "abcdefghijklmnopqrstuvwxyz" }, 59 { "relocate .bss reference", 2, "" }, 60 { "relocate .data reference", 3, "abcdexghijklmnopqrstuvwxyz" }, 61 { "relocate .bss reference", 4, "\0\0hello" }, 62 }; 63 64 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 65 err = bpf_map_lookup_elem(map_fd, &tests[i].key, str); 66 CHECK(err || memcmp(str, tests[i].str, sizeof(str)), 67 tests[i].name, "err %d result \'%s\' expected \'%s\'\n", 68 err, str, tests[i].str); 69 } 70 } 71 72 struct foo { 73 __u8 a; 74 __u32 b; 75 __u64 c; 76 }; 77 78 static void test_global_data_struct(struct bpf_object *obj, __u32 duration) 79 { 80 int i, err, map_fd; 81 struct foo val; 82 83 map_fd = bpf_find_map(__func__, obj, "result_struct"); 84 if (map_fd < 0) { 85 error_cnt++; 86 return; 87 } 88 89 struct { 90 char *name; 91 uint32_t key; 92 struct foo val; 93 } tests[] = { 94 { "relocate .rodata reference", 0, { 42, 0xfefeefef, 0x1111111111111111ULL, } }, 95 { "relocate .bss reference", 1, { } }, 96 { "relocate .rodata reference", 2, { } }, 97 { "relocate .data reference", 3, { 41, 0xeeeeefef, 0x2111111111111111ULL, } }, 98 }; 99 100 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 101 err = bpf_map_lookup_elem(map_fd, &tests[i].key, &val); 102 CHECK(err || memcmp(&val, &tests[i].val, sizeof(val)), 103 tests[i].name, "err %d result { %u, %u, %llu } expected { %u, %u, %llu }\n", 104 err, val.a, val.b, val.c, tests[i].val.a, tests[i].val.b, tests[i].val.c); 105 } 106 } 107 108 static void test_global_data_rdonly(struct bpf_object *obj, __u32 duration) 109 { 110 int err = -ENOMEM, map_fd, zero = 0; 111 struct bpf_map *map; 112 __u8 *buff; 113 114 map = bpf_object__find_map_by_name(obj, "test_glo.rodata"); 115 if (!map || !bpf_map__is_internal(map)) { 116 error_cnt++; 117 return; 118 } 119 120 map_fd = bpf_map__fd(map); 121 if (map_fd < 0) { 122 error_cnt++; 123 return; 124 } 125 126 buff = malloc(bpf_map__def(map)->value_size); 127 if (buff) 128 err = bpf_map_update_elem(map_fd, &zero, buff, 0); 129 free(buff); 130 CHECK(!err || errno != EPERM, "test .rodata read-only map", 131 "err %d errno %d\n", err, errno); 132 } 133 134 void test_global_data(void) 135 { 136 const char *file = "./test_global_data.o"; 137 __u32 duration = 0, retval; 138 struct bpf_object *obj; 139 int err, prog_fd; 140 141 err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd); 142 if (CHECK(err, "load program", "error %d loading %s\n", err, file)) 143 return; 144 145 err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), 146 NULL, NULL, &retval, &duration); 147 CHECK(err || retval, "pass global data run", 148 "err %d errno %d retval %d duration %d\n", 149 err, errno, retval, duration); 150 151 test_global_data_number(obj, duration); 152 test_global_data_string(obj, duration); 153 test_global_data_struct(obj, duration); 154 test_global_data_rdonly(obj, duration); 155 156 bpf_object__close(obj); 157 } 158