d011079fb0bfe6dbd6c963c342787fc25e97b819
[muen/linux.git] / tools / testing / selftests / bpf / prog_tests / global_data.c
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 }