]> granicus.if.org Git - strace/blob - tests/bpf.c
xlat: add BPF_F_CLONE to bpf_map_flags
[strace] / tests / bpf.c
1 /*
2  * Check bpf syscall decoding.
3  *
4  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2015-2019 The strace developers.
6  * All rights reserved.
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "tests.h"
12
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <stdint.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #include "scno.h"
20
21 #ifdef HAVE_LINUX_BPF_H
22 # include <linux/bpf.h>
23 #endif
24
25 #include "bpf_attr.h"
26 #include "print_fields.h"
27
28 #include "xlat.h"
29 #include "xlat/bpf_commands.h"
30
31 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
32 # define BIG_ADDR(addr64_, addr32_) addr64_
33 # define BIG_ADDR_MAYBE(addr_)
34 #elif defined __arm__ || defined __i386__ || defined __mips__ \
35    || defined __powerpc__ || defined __riscv__ || defined __s390__ \
36    || defined __sparc__ || defined __tile__
37 # define BIG_ADDR(addr64_, addr32_) addr64_ " or " addr32_
38 # define BIG_ADDR_MAYBE(addr_) addr_ " or "
39 #else
40 # define BIG_ADDR(addr64_, addr32_) addr32_
41 # define BIG_ADDR_MAYBE(addr_)
42 #endif
43
44 #ifndef HAVE_STRUCT_BPF_INSN
45 struct bpf_insn {
46         uint8_t code;
47         uint8_t dst_reg:4;
48         uint8_t src_reg:4;
49         int16_t off;
50         int32_t imm;
51 };
52 #endif
53
54 #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data
55
56 union bpf_attr_data {
57         BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE);
58         BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM);
59         BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM);
60         BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM);
61         BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY);
62         BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD);
63         BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN);
64         BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH);
65         BPF_ATTR_DATA_FIELD(BPF_PROG_DETACH);
66         BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN);
67         BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID);
68         BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
69         BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
70         BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
71         BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
72         BPF_ATTR_DATA_FIELD(BPF_RAW_TRACEPOINT_OPEN);
73         BPF_ATTR_DATA_FIELD(BPF_BTF_LOAD);
74         BPF_ATTR_DATA_FIELD(BPF_BTF_GET_FD_BY_ID);
75         BPF_ATTR_DATA_FIELD(BPF_TASK_FD_QUERY);
76         BPF_ATTR_DATA_FIELD(BPF_MAP_FREEZE);
77         char char_data[256];
78 };
79
80 struct bpf_attr_check {
81         union bpf_attr_data data;
82         size_t size;
83         const char *str;
84         void (*init_fn)(struct bpf_attr_check *check);
85         void (*print_fn)(const struct bpf_attr_check *check,
86                          unsigned long addr);
87 };
88
89 struct bpf_check {
90         kernel_ulong_t cmd;
91         const char *cmd_str;
92         const struct bpf_attr_check *checks;
93         size_t count;
94 };
95
96 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
97 static const char *errstr;
98 static unsigned int sizeof_attr = sizeof(union bpf_attr_data);
99 static unsigned int page_size;
100 static unsigned long end_of_page;
101
102 static long
103 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
104 {
105         long rc = syscall(__NR_bpf, cmd, attr, size);
106
107         errstr = sprintrc(rc);
108
109 #ifdef INJECT_RETVAL
110         if (rc != INJECT_RETVAL)
111                 error_msg_and_fail("Got a return value of %ld != %d",
112                                    rc, INJECT_RETVAL);
113
114         static char inj_errstr[4096];
115
116         snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
117         errstr = inj_errstr;
118 #endif
119
120         return rc;
121 }
122
123 #if VERBOSE
124 # define print_extra_data(addr_, offs_, size_) \
125         do { \
126                 printf("/* bytes %u..%u */ ", (offs_), (size_) + (offs_) - 1); \
127                 print_quoted_hex((addr_) + (offs_), (size_)); \
128         } while (0)
129 #else
130 # define print_extra_data(addr_, offs_, size_) printf("...")
131 #endif
132
133 static void
134 print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr)
135 {
136         if (check->print_fn)
137                 check->print_fn(check, addr);
138         else
139                 printf("%s", check->str);
140 }
141
142 static void
143 test_bpf(const struct bpf_check *cmd_check)
144 {
145         const struct bpf_attr_check *check = 0;
146         const union bpf_attr_data *data = 0;
147         unsigned int offset = 0;
148
149         /* zero addr */
150         sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data));
151         printf("bpf(%s, NULL, %u) = %s\n",
152                cmd_check->cmd_str, sizeof_attr, errstr);
153
154         /* zero size */
155         unsigned long addr = end_of_page - sizeof_attr;
156         sys_bpf(cmd_check->cmd, addr, long_bits);
157         printf("bpf(%s, %#lx, 0) = %s\n",
158                cmd_check->cmd_str, addr, errstr);
159
160         for (size_t i = 0; i < cmd_check->count; i++) {
161                 check = &cmd_check->checks[i];
162                 if (check->init_fn)
163                         check->init_fn((struct bpf_attr_check *) check);
164                 data = &check->data;
165                 offset = check->size;
166
167                 addr = end_of_page - offset;
168                 memcpy((void *) addr, data, offset);
169
170                 /* starting piece of bpf_attr_data */
171                 sys_bpf(cmd_check->cmd, addr, offset);
172                 printf("bpf(%s, {", cmd_check->cmd_str);
173                 print_bpf_attr(check, addr);
174                 printf("}, %u) = %s\n", offset, errstr);
175
176                 /* short read of the starting piece */
177                 sys_bpf(cmd_check->cmd, addr + 1, offset);
178                 printf("bpf(%s, %#lx, %u) = %s\n",
179                        cmd_check->cmd_str, addr + 1, offset, errstr);
180         }
181
182         if (offset < sizeof_attr) {
183                 /* short read of the whole bpf_attr_data */
184                 memcpy((void *) end_of_page - sizeof_attr + 1, data, offset);
185                 addr = end_of_page - sizeof_attr + 1;
186                 memset((void *) addr + offset, 0, sizeof_attr - offset - 1);
187                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
188                 printf("bpf(%s, %#lx, %u) = %s\n",
189                        cmd_check->cmd_str, addr, sizeof_attr, errstr);
190
191                 /* the whole bpf_attr_data */
192                 memcpy((void *) end_of_page - sizeof_attr, data, offset);
193                 addr = end_of_page - sizeof_attr;
194                 memset((void *) addr + offset, 0, sizeof_attr - offset);
195                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
196                 printf("bpf(%s, {", cmd_check->cmd_str);
197                 print_bpf_attr(check, addr);
198                 printf("}, %u) = %s\n", sizeof_attr, errstr);
199
200                 /* non-zero bytes after the relevant part */
201                 fill_memory_ex((void *) addr + offset,
202                                sizeof_attr - offset, '0', 10);
203                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
204                 printf("bpf(%s, {", cmd_check->cmd_str);
205                 print_bpf_attr(check, addr);
206                 printf(", ");
207                 print_extra_data((char *) addr, offset,
208                                  sizeof_attr - offset);
209                 printf("}, %u) = %s\n", sizeof_attr, errstr);
210         }
211
212         /* short read of the whole page */
213         memcpy((void *) end_of_page - page_size + 1, data, offset);
214         addr = end_of_page - page_size + 1;
215         memset((void *) addr + offset, 0, page_size - offset - 1);
216         sys_bpf(cmd_check->cmd, addr, page_size);
217         printf("bpf(%s, %#lx, %u) = %s\n",
218                cmd_check->cmd_str, addr, page_size, errstr);
219
220         /* the whole page */
221         memcpy((void *) end_of_page - page_size, data, offset);
222         addr = end_of_page - page_size;
223         memset((void *) addr + offset, 0, page_size - offset);
224         sys_bpf(cmd_check->cmd, addr, page_size);
225         printf("bpf(%s, {", cmd_check->cmd_str);
226         print_bpf_attr(check, addr);
227         printf("}, %u) = %s\n", page_size, errstr);
228
229         /* non-zero bytes after the whole bpf_attr_data */
230         fill_memory_ex((void *) addr + offset,
231                        page_size - offset, '0', 10);
232         sys_bpf(cmd_check->cmd, addr, page_size);
233         printf("bpf(%s, {", cmd_check->cmd_str);
234         print_bpf_attr(check, addr);
235         printf(", ");
236         print_extra_data((char *) addr, offset,
237                          page_size - offset);
238         printf("}, %u) = %s\n", page_size, errstr);
239
240         /* more than a page */
241         sys_bpf(cmd_check->cmd, addr, page_size + 1);
242         printf("bpf(%s, %#lx, %u) = %s\n",
243                cmd_check->cmd_str, addr, page_size + 1, errstr);
244 }
245
246 static void
247 init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check)
248 {
249         struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
250         attr->map_ifindex = ifindex_lo();
251 }
252
253 static struct bpf_attr_check BPF_MAP_CREATE_checks[] = {
254         {
255                 .data = { .BPF_MAP_CREATE_data = { .map_type = 2 } },
256                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_type),
257                 .str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
258                        ", max_entries=0"
259         },
260         { /* 1 */
261                 .data = { .BPF_MAP_CREATE_data = {
262                         .map_type = 20,
263                         .key_size = 4,
264                         .value_size = 8,
265                         .max_entries = 256,
266                         .map_flags = 63,
267                         .inner_map_fd = -1,
268                         .numa_node = 3141592653,
269                         .map_name = "0123456789abcde",
270                 } },
271                 .size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8,
272                 .str = "map_type=BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, key_size=4"
273                        ", value_size=8, max_entries=256"
274                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
275                                    "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY"
276                                    "|BPF_F_STACK_BUILD_ID"
277                        ", inner_map_fd=-1"
278                        ", numa_node=3141592653"
279                        ", map_name=\"0123456\"...",
280
281         },
282         { /* 2 */
283                 .data = { .BPF_MAP_CREATE_data = {
284                         .map_type = 25,
285                         .key_size = 0xface1e55,
286                         .value_size = 0xbadc0ded,
287                         .max_entries = 0xbeefcafe,
288                         .map_flags = 0xfffffc00,
289                         .inner_map_fd = 2718281828,
290                         .numa_node = -1,
291                         .map_name = "",
292                         .map_ifindex = 3141592653,
293                 } },
294                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
295                 .str = "map_type=0x19 /* BPF_MAP_TYPE_??? */"
296                        ", key_size=4207812181, value_size=3134983661"
297                        ", max_entries=3203386110"
298                        ", map_flags=0xfffffc00 /* BPF_F_??? */"
299                        ", inner_map_fd=-1576685468"
300                        ", map_name=\"\", map_ifindex=3141592653",
301
302         },
303         { /* 3 */
304                 .data = { .BPF_MAP_CREATE_data = {
305                         .map_type = 0xdeadf00d,
306                         .key_size = 0xface1e55,
307                         .value_size = 0xbadc0ded,
308                         .max_entries = 0xbeefcafe,
309                         .map_flags = 0xc0dedead,
310                         .inner_map_fd = 2718281828,
311                         .numa_node = -1,
312                 } },
313                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags),
314                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
315                        ", key_size=4207812181, value_size=3134983661"
316                        ", max_entries=3203386110"
317                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
318                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
319                                    "|BPF_F_RDONLY_PROG|BPF_F_CLONE|0xc0dedc00",
320         },
321         { /* 4 */
322                 .data = { .BPF_MAP_CREATE_data = {
323                         .map_type = 0xdeadf00d,
324                         .key_size = 0xface1e55,
325                         .value_size = 0xbadc0ded,
326                         .max_entries = 0xbeefcafe,
327                         .map_flags = 0xc0dedead,
328                         .inner_map_fd = 2718281828,
329                         .numa_node = -1,
330                 } },
331                 .size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd),
332                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
333                        ", key_size=4207812181, value_size=3134983661"
334                        ", max_entries=3203386110"
335                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
336                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
337                                    "|BPF_F_RDONLY_PROG|BPF_F_CLONE|0xc0dedc00"
338                        ", inner_map_fd=-1576685468",
339         },
340         { /* 5 */
341                 .data = { .BPF_MAP_CREATE_data = {
342                         .map_type = 0xdeadf00d,
343                         .key_size = 0xface1e55,
344                         .value_size = 0xbadc0ded,
345                         .max_entries = 0xbeefcafe,
346                         .map_flags = 0xc0dedead,
347                         .inner_map_fd = 2718281828,
348                         .numa_node = -1,
349                 } },
350                 .size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node),
351                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
352                        ", key_size=4207812181, value_size=3134983661"
353                        ", max_entries=3203386110"
354                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
355                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
356                                    "|BPF_F_RDONLY_PROG|BPF_F_CLONE|0xc0dedc00"
357                        ", inner_map_fd=-1576685468"
358                        ", numa_node=4294967295 /* NUMA_NO_NODE */",
359         },
360         { /* 6 */
361                 .data = { .BPF_MAP_CREATE_data = {
362                         .map_type = 0xdeadf00d,
363                         .key_size = 0xface1e55,
364                         .value_size = 0xbadc0ded,
365                         .max_entries = 0xbeefcafe,
366                         .map_flags = 0xc0dedead,
367                         .inner_map_fd = 2718281828,
368                         .numa_node = -1,
369                         .map_name = "fedcba9876543210",
370                 } },
371                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_name),
372                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
373                        ", key_size=4207812181, value_size=3134983661"
374                        ", max_entries=3203386110"
375                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
376                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
377                                    "|BPF_F_RDONLY_PROG|BPF_F_CLONE|0xc0dedc00"
378                        ", inner_map_fd=-1576685468"
379                        ", numa_node=4294967295 /* NUMA_NO_NODE */"
380                        ", map_name=\"fedcba987654321\"...",
381         },
382         { /* 7 */
383                 .data = { .BPF_MAP_CREATE_data = {
384                         .map_type = 0xdeadf00d,
385                         .key_size = 0xface1e55,
386                         .value_size = 0xbadc0ded,
387                         .max_entries = 0xbeefcafe,
388                         .map_flags = 0xc0dedead,
389                         .inner_map_fd = 2718281828,
390                         .numa_node = -1,
391                         .map_name = "0123456789abcde",
392                 } },
393                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
394                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
395                        ", key_size=4207812181, value_size=3134983661"
396                        ", max_entries=3203386110"
397                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
398                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
399                                    "|BPF_F_RDONLY_PROG|BPF_F_CLONE|0xc0dedc00"
400                        ", inner_map_fd=-1576685468"
401                        ", numa_node=4294967295 /* NUMA_NO_NODE */"
402                        ", map_name=\"0123456789abcde\""
403                        ", map_ifindex=" IFINDEX_LO_STR,
404                 .init_fn = init_BPF_MAP_CREATE_attr7,
405         },
406         { /* 8 */
407                 .data = { .BPF_MAP_CREATE_data = {
408                         .btf_fd = 0xbadc0ded,
409                         .btf_key_type_id = 0xfacefeed,
410                         .btf_value_type_id = 0xcafef00d
411                 } },
412                 .size = offsetofend(struct BPF_MAP_CREATE_struct,
413                                     btf_value_type_id),
414                 .str = "map_type=BPF_MAP_TYPE_UNSPEC"
415                        ", key_size=0"
416                        ", value_size=0"
417                        ", max_entries=0"
418                        ", map_flags=0"
419                        ", inner_map_fd=0"
420                        ", map_name=\"\""
421                        ", map_ifindex=0"
422                        ", btf_fd=-1159983635"
423                        ", btf_key_type_id=4207869677"
424                        ", btf_value_type_id=3405705229"
425         },
426 };
427
428 static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = {
429         {
430                 .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } },
431                 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd),
432                 .str = "map_fd=-1, key=NULL, value=NULL"
433         },
434         {
435                 .data = { .BPF_MAP_LOOKUP_ELEM_data = {
436                         .map_fd = -1,
437                         .key = 0xdeadbeef,
438                         .value = 0xbadc0ded
439                 } },
440                 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, value),
441                 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
442         }
443 };
444
445 #define BPF_MAP_LOOKUP_AND_DELETE_ELEM_checks BPF_MAP_LOOKUP_ELEM_checks
446
447 static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = {
448         {
449                 .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } },
450                 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd),
451                 .str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY"
452         },
453         {
454                 .data = { .BPF_MAP_UPDATE_ELEM_data = {
455                         .map_fd = -1,
456                         .key = 0xdeadbeef,
457                         .value = 0xbadc0ded,
458                         .flags = 2
459                 } },
460                 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags),
461                 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
462                        ", flags=BPF_EXIST"
463         }
464 };
465
466 static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = {
467         {
468                 .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } },
469                 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd),
470                 .str = "map_fd=-1, key=NULL"
471         },
472         {
473                 .data = { .BPF_MAP_DELETE_ELEM_data = {
474                         .map_fd = -1,
475                         .key = 0xdeadbeef
476                 } },
477                 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key),
478                 .str = "map_fd=-1, key=0xdeadbeef"
479         }
480 };
481
482 static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = {
483         {
484                 .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } },
485                 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd),
486                 .str = "map_fd=-1, key=NULL, next_key=NULL"
487         },
488         {
489                 .data = { .BPF_MAP_GET_NEXT_KEY_data = {
490                         .map_fd = -1,
491                         .key = 0xdeadbeef,
492                         .next_key = 0xbadc0ded
493                 } },
494                 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key),
495                 .str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded"
496         }
497 };
498
499 static const struct bpf_attr_check BPF_MAP_FREEZE_checks[] = {
500         {
501                 .data = { .BPF_MAP_FREEZE_data = { .map_fd = -1 } },
502                 .size = offsetofend(struct BPF_MAP_FREEZE_struct, map_fd),
503                 .str = "map_fd=-1"
504         }
505 };
506
507 static const struct bpf_insn insns[] = {
508         {
509                 .code = 0x95,
510                 .dst_reg = 10,
511                 .src_reg = 11,
512                 .off = 0xdead,
513                 .imm = 0xbadc0ded,
514         },
515 };
516 static const char license[] = "GPL";
517 static const char pathname[] = "/sys/fs/bpf/foo/bar";
518
519 static char *log_buf;
520 /*
521  * This has to be a macro, otherwise the compiler complains that
522  * initializer element is not constant.
523  */
524 #define log_buf_size 4096U
525
526 static inline char *
527 get_log_buf(void)
528 {
529         if (!log_buf)
530                 log_buf = tail_alloc(log_buf_size);
531         return log_buf;
532 }
533
534 static inline char *
535 get_log_buf_tail(void)
536 {
537         return get_log_buf() + log_buf_size;
538 }
539
540 #if VERBOSE
541 # define INSNS_FMT \
542         "[{code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_10" \
543         ", src_reg=0xb /* BPF_REG_??? */, off=%d, imm=%#x}]"
544 # define INSNS_ARG insns[0].off, insns[0].imm
545 #else
546 # define INSNS_FMT "%p"
547 # define INSNS_ARG insns
548 #endif
549
550 static void
551 init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check)
552 {
553         struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
554
555         attr->insns = (uintptr_t) insns;
556         attr->license = (uintptr_t) license;
557         attr->log_buf = (uintptr_t) get_log_buf_tail();
558 }
559
560 static void
561 print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr)
562 {
563         printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u"
564                ", insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828"
565                ", log_size=%u, log_buf=%p"
566                ", kern_version=KERNEL_VERSION(51966, 240, 13)"
567                ", prog_flags=0x10 /* BPF_F_??? */"
568                ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
569                (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license,
570                log_buf_size, get_log_buf_tail());
571 }
572
573 static void
574 init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check)
575 {
576         struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
577
578         attr->insns = (uintptr_t) insns;
579         attr->license = (uintptr_t) license;
580         attr->log_buf = (uintptr_t) get_log_buf();
581         attr->prog_ifindex = ifindex_lo();
582
583         strncpy(log_buf, "log test", 9);
584 }
585
586 static void
587 print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr)
588 {
589         printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT
590                ", license=\"%s\", log_level=2718281828, log_size=4"
591                ", log_buf=\"log \"..."
592                ", kern_version=KERNEL_VERSION(51966, 240, 13)"
593                ", prog_flags=BPF_F_STRICT_ALIGNMENT|BPF_F_ANY_ALIGNMENT"
594                "|BPF_F_TEST_RND_HI32|BPF_F_TEST_STATE_FREQ|0x10"
595                ", prog_name=\"0123456789abcde\"..., prog_ifindex=%s"
596                ", expected_attach_type=BPF_CGROUP_INET6_BIND",
597                (unsigned int) ARRAY_SIZE(insns), INSNS_ARG,
598                license, IFINDEX_LO_STR);
599 }
600
601 static struct bpf_attr_check BPF_PROG_LOAD_checks[] = {
602         {
603                 .data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } },
604                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type),
605                 .str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER"
606                        ", insn_cnt=0, insns=NULL, license=NULL"
607         },
608         { /* 1 */
609                 .data = { .BPF_PROG_LOAD_data = {
610                         .prog_type = 25,
611                         .insn_cnt = 0xbadc0ded,
612                         .insns = 0,
613                         .license = 0,
614                         .log_level = 42,
615                         .log_size = 3141592653U,
616                         .log_buf = 0,
617                         .kern_version = 0xcafef00d,
618                         .prog_flags = 0,
619                 } },
620                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags),
621                 .str = "prog_type=0x19 /* BPF_PROG_TYPE_??? */"
622                        ", insn_cnt=3134983661, insns=NULL, license=NULL"
623                        ", log_level=42, log_size=3141592653, log_buf=NULL"
624                        ", kern_version=KERNEL_VERSION(51966, 240, 13)"
625                        ", prog_flags=0",
626         },
627         { /* 2 */
628                 .data = { .BPF_PROG_LOAD_data = {
629                         .prog_type = 20,
630                         .insn_cnt = 0xbadc0ded,
631                         .insns = 0xffffffff00000000,
632                         .license = 0xffffffff00000000,
633                         .log_level = 2718281828U,
634                         .log_size = log_buf_size,
635                         .log_buf = 0xffffffff00000000,
636                         .kern_version = 0xcafef00d,
637                         .prog_flags = 1,
638                         .prog_name = "fedcba987654321",
639                 } },
640                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
641                 .str = "prog_type=BPF_PROG_TYPE_SK_REUSEPORT"
642                        ", insn_cnt=3134983661"
643                        ", insns=" BIG_ADDR("0xffffffff00000000", "NULL")
644                        ", license=" BIG_ADDR("0xffffffff00000000", "NULL")
645                        ", log_level=2718281828, log_size=4096"
646                        ", log_buf=" BIG_ADDR("0xffffffff00000000", "NULL")
647                        ", kern_version=KERNEL_VERSION(51966, 240, 13)"
648                        ", prog_flags=BPF_F_STRICT_ALIGNMENT"
649                        ", prog_name=\"fedcba987654321\"",
650         },
651         { /* 3 */
652                 .data = { .BPF_PROG_LOAD_data = {
653                         .prog_type = 1,
654                         .insn_cnt = ARRAY_SIZE(insns),
655                         .log_level = 2718281828U,
656                         .log_size = log_buf_size,
657                         .kern_version = 0xcafef00d,
658                         .prog_flags = 16,
659                         .prog_name = "0123456789abcdef",
660                         .prog_ifindex = 0xbeeffeed,
661                 } },
662                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
663                 .init_fn = init_BPF_PROG_LOAD_attr3,
664                 .print_fn = print_BPF_PROG_LOAD_attr3
665         },
666         { /* 4 */
667                 .data = { .BPF_PROG_LOAD_data = {
668                         .prog_type = 0,
669                         .insn_cnt = ARRAY_SIZE(insns),
670                         .log_level = 2718281828U,
671                         .log_size = 4,
672                         .kern_version = 0xcafef00d,
673                         .prog_flags = 0x1f,
674                         .prog_name = "0123456789abcdef",
675                         .expected_attach_type = 9,
676                 } },
677                 .size = offsetofend(struct BPF_PROG_LOAD_struct,
678                                     expected_attach_type),
679                 .init_fn = init_BPF_PROG_LOAD_attr4,
680                 .print_fn = print_BPF_PROG_LOAD_attr4
681         },
682         { /* 5 */
683                 .data = { .BPF_PROG_LOAD_data = {
684                         .prog_flags = 2,
685                         .expected_attach_type = 17,
686                         .prog_btf_fd = 0xbadc0ded,
687                         .func_info_rec_size = 0xdad1bef2,
688                         .func_info = 0xfac1fed2fac3fed4,
689                         .func_info_cnt = 0xdad3bef4,
690                         .line_info_rec_size = 0xdad5bef6,
691                         .line_info = 0xfac5fed5fac7fed8,
692                         .line_info_cnt = 0xdad7bef8
693                 } },
694                 .size = offsetofend(struct BPF_PROG_LOAD_struct,
695                                     line_info_cnt),
696                 .str = "prog_type=BPF_PROG_TYPE_UNSPEC"
697                        ", insn_cnt=0"
698                        ", insns=NULL"
699                        ", license=NULL"
700                        ", log_level=0"
701                        ", log_size=0"
702                        ", log_buf=NULL"
703                        ", kern_version=KERNEL_VERSION(0, 0, 0)"
704                        ", prog_flags=BPF_F_ANY_ALIGNMENT"
705                        ", prog_name=\"\""
706                        ", prog_ifindex=0"
707                        ", expected_attach_type=BPF_FLOW_DISSECTOR"
708                        ", prog_btf_fd=-1159983635"
709                        ", func_info_rec_size=3671178994"
710                        ", func_info=0xfac1fed2fac3fed4"
711                        ", func_info_cnt=3671310068"
712                        ", line_info_rec_size=3671441142"
713                        ", line_info=0xfac5fed5fac7fed8"
714                        ", line_info_cnt=3671572216"
715         },
716 };
717
718 static void
719 init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check)
720 {
721         struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data;
722         attr->pathname = (uintptr_t) pathname;
723 }
724
725 static struct bpf_attr_check BPF_OBJ_PIN_checks[] = {
726         {
727                 .data = { .BPF_OBJ_PIN_data = { .pathname = 0 } },
728                 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
729                 .str = "pathname=NULL, bpf_fd=0"
730         },
731         {
732                 .data = { .BPF_OBJ_PIN_data = {
733                         .pathname = 0xFFFFFFFFFFFFFFFFULL
734                 } },
735                 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
736                 .str = "pathname=" BIG_ADDR("0xffffffffffffffff", "0xffffffff")
737                        ", bpf_fd=0",
738         },
739         {
740                 .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } },
741                 .size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd),
742                 .init_fn = init_BPF_OBJ_PIN_attr,
743                 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
744         },
745         {
746                 .data = { .BPF_OBJ_PIN_data = {
747                         .bpf_fd = -1,
748                         .file_flags = 0x18
749                 } },
750                 .size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags),
751                 .init_fn = init_BPF_OBJ_PIN_attr,
752                 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
753                        ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY"
754         }
755 };
756
757 #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks
758
759 static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = {
760         {
761                 .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } },
762                 .size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd),
763                 .str = "target_fd=-1, attach_bpf_fd=0"
764                        ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0"
765         },
766         {
767                 .data = { .BPF_PROG_ATTACH_data = {
768                         .target_fd = -1,
769                         .attach_bpf_fd = -2,
770                         .attach_type = 2,
771                         .attach_flags = 1
772                 } },
773                 .size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags),
774                 .str = "target_fd=-1, attach_bpf_fd=-2"
775                        ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
776                        ", attach_flags=BPF_F_ALLOW_OVERRIDE"
777         }
778 };
779
780
781 static const struct bpf_attr_check BPF_PROG_DETACH_checks[] = {
782         {
783                 .data = { .BPF_PROG_DETACH_data = { .target_fd = -1 } },
784                 .size = offsetofend(struct BPF_PROG_DETACH_struct, target_fd),
785                 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS"
786         },
787         {
788                 .data = { .BPF_PROG_DETACH_data = {
789                         .target_fd = -1,
790                         .attach_type = 2
791                 } },
792                 .size = offsetofend(struct BPF_PROG_DETACH_struct, attach_type),
793                 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE"
794         }
795 };
796
797 static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = {
798         {
799                 .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } },
800                 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd),
801                 .str = "test={prog_fd=-1, retval=0, data_size_in=0"
802                        ", data_size_out=0, data_in=NULL, data_out=NULL"
803                        ", repeat=0, duration=0}"
804         },
805         {
806                 .data = { .BPF_PROG_TEST_RUN_data = {
807                         .prog_fd = -1,
808                         .retval = 0xfac1fed2,
809                         .data_size_in = 0xfac3fed4,
810                         .data_size_out = 0xfac5fed6,
811                         .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
812                         .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
813                         .repeat = 0xfac7fed8,
814                         .duration = 0xfac9feda
815                 } },
816                 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration),
817                 .str = "test={prog_fd=-1, retval=4207017682"
818                        ", data_size_in=4207148756, data_size_out=4207279830"
819                        ", data_in=0xfacef11dbadc2ded"
820                        ", data_out=0xfacef33dbadc4ded"
821                        ", repeat=4207410904, duration=4207541978}"
822         },
823         {
824                 .data = { .BPF_PROG_TEST_RUN_data = {
825                         .prog_fd = -1,
826                         .retval = 0xfac1fed2,
827                         .data_size_in = 0xfac3fed4,
828                         .data_size_out = 0xfac5fed6,
829                         .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
830                         .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
831                         .repeat = 0xfac7fed8,
832                         .duration = 0xfac9feda,
833                         .ctx_size_in = 0xfacbfedc,
834                         .ctx_size_out = 0xfacdfede,
835                         .ctx_in = (uint64_t) 0xfacef55dbadc6dedULL,
836                         .ctx_out = (uint64_t) 0xfacef77dbadc8dedULL
837                 } },
838                 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, ctx_out),
839                 .str = "test={prog_fd=-1, retval=4207017682"
840                        ", data_size_in=4207148756, data_size_out=4207279830"
841                        ", data_in=0xfacef11dbadc2ded"
842                        ", data_out=0xfacef33dbadc4ded"
843                        ", repeat=4207410904"
844                        ", duration=4207541978"
845                        ", ctx_size_in=4207673052"
846                        ", ctx_size_out=4207804126"
847                        ", ctx_in=0xfacef55dbadc6ded"
848                        ", ctx_out=0xfacef77dbadc8ded}"
849         }
850 };
851
852 static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = {
853         {
854                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
855                         .start_id = 0xdeadbeef
856                 } },
857                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id),
858                 .str = "start_id=3735928559, next_id=0"
859         },
860         {
861                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
862                         .start_id = 0xdeadbeef
863                 } },
864                 .size = 1,
865                 .str = "start_id="
866 #if WORDS_BIGENDIAN
867                        "3724541952"     /* 0xde000000 */
868 #else
869                        "239"            /* 0x000000ef */
870 #endif
871                        ", next_id=0"
872         },
873         {
874                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
875                         .start_id = 0xbadc0ded,
876                         .next_id = 0xcafef00d
877                 } },
878                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id),
879                 .str = "start_id=3134983661, next_id=3405705229"
880         },
881         {
882                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
883                         .start_id = 0xbadc0ded,
884                         .next_id = 0xcafef00d,
885                         .open_flags = 0xffffff27
886                 } },
887                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, open_flags),
888                 .str = "start_id=3134983661, next_id=3405705229"
889                        ", open_flags=0xffffff27 /* BPF_F_??? */"
890         }
891 };
892
893 #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
894
895 static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = {
896         {
897                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
898                         .prog_id = 0xdeadbeef
899                 } },
900                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id),
901                 .str = "prog_id=3735928559, next_id=0"
902         },
903         {
904                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
905                         .prog_id = 0xbadc0ded,
906                         .next_id = 0xcafef00d
907                 } },
908                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, next_id),
909                 .str = "prog_id=3134983661, next_id=3405705229"
910         },
911         {
912                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
913                         .prog_id = 0xbadc0ded,
914                         .next_id = 0xcafef00d,
915                         .open_flags = 0xffffff27
916                 } },
917                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags),
918                 .str = "prog_id=3134983661, next_id=3405705229"
919                        ", open_flags=0xffffff27 /* BPF_F_??? */"
920         }
921 };
922
923 static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = {
924         {
925                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
926                         .map_id = 0xdeadbeef
927                 } },
928                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id),
929                 .str = "map_id=3735928559, next_id=0"
930         },
931         {
932                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
933                         .map_id = 0xbadc0ded,
934                         .next_id = 0xcafef00d
935                 } },
936                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id),
937                 .str = "map_id=3134983661, next_id=3405705229"
938         },
939         {
940                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
941                         .map_id = 0xbadc0ded,
942                         .next_id = 0xcafef00d,
943                         .open_flags = 0xffffff27
944                 } },
945                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags),
946                 .str = "map_id=3134983661, next_id=3405705229"
947                        ", open_flags=0xffffff27 /* BPF_F_??? */"
948         }
949 };
950
951 static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
952         {
953                 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } },
954                 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd),
955                 .str = "info={bpf_fd=-1, info_len=0, info=NULL}"
956         },
957         {
958                 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = {
959                         .bpf_fd = -1,
960                         .info_len = 0xdeadbeef,
961                         .info = (uint64_t) 0xfacefeedbadc0dedULL
962                 } },
963                 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info),
964                 .str = "info={bpf_fd=-1, info_len=3735928559"
965                        ", info=0xfacefeedbadc0ded}"
966         }
967 };
968
969
970 static uint32_t prog_load_ids[] = { 0, 1, 0xffffffff, 2718281828, };
971 uint32_t *prog_load_ids_ptr;
972
973 static void
974 init_BPF_PROG_QUERY_attr4(struct bpf_attr_check *check)
975 {
976         struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
977
978         if (!prog_load_ids_ptr)
979                 prog_load_ids_ptr = tail_memdup(prog_load_ids,
980                                                 sizeof(prog_load_ids));
981
982         attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
983         attr->prog_cnt = ARRAY_SIZE(prog_load_ids);
984 }
985
986 static void
987 print_BPF_PROG_QUERY_attr4(const struct bpf_attr_check *check, unsigned long addr)
988 {
989         printf("query={target_fd=-1153374643"
990                ", attach_type=0xfeedface /* BPF_??? */"
991                ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
992                ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
993 #if defined(INJECT_RETVAL) && INJECT_RETVAL > 0
994                ", prog_ids=[0, 1, 4294967295, 2718281828], prog_cnt=4}"
995 #else
996                ", prog_ids=%p, prog_cnt=4}", prog_load_ids_ptr
997 #endif
998                );
999 }
1000
1001 static void
1002 init_BPF_PROG_QUERY_attr5(struct bpf_attr_check *check)
1003 {
1004         struct BPF_PROG_QUERY_struct *attr = &check->data.BPF_PROG_QUERY_data;
1005
1006         if (!prog_load_ids_ptr)
1007                 prog_load_ids_ptr = tail_memdup(prog_load_ids,
1008                                                 sizeof(prog_load_ids));
1009
1010         attr->prog_ids = (uintptr_t) prog_load_ids_ptr;
1011         attr->prog_cnt = ARRAY_SIZE(prog_load_ids) + 1;
1012 }
1013
1014 static void
1015 print_BPF_PROG_QUERY_attr5(const struct bpf_attr_check *check, unsigned long addr)
1016 {
1017         printf("query={target_fd=-1153374643"
1018                ", attach_type=0xfeedface /* BPF_??? */"
1019                ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1020                ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
1021 #if defined(INJECT_RETVAL) && INJECT_RETVAL > 0
1022                ", prog_ids=[0, 1, 4294967295, 2718281828, ... /* %p */]"
1023                ", prog_cnt=5}",
1024                prog_load_ids_ptr + ARRAY_SIZE(prog_load_ids)
1025 #else
1026                ", prog_ids=%p, prog_cnt=5}", prog_load_ids_ptr
1027 #endif
1028                );
1029 }
1030
1031 static struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
1032         {
1033                 .data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
1034                 .size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
1035                 .str = "query={target_fd=-1"
1036                        ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
1037                        ", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
1038         },
1039         { /* 1 */
1040                 .data = { .BPF_PROG_QUERY_data = {
1041                         .target_fd = 3141592653U,
1042                         .attach_type = 16,
1043                         .query_flags = 1,
1044                         .attach_flags = 3,
1045                 } },
1046                 .size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
1047                 .str = "query={target_fd=-1153374643"
1048                        ", attach_type=BPF_LIRC_MODE2"
1049                        ", query_flags=BPF_F_QUERY_EFFECTIVE"
1050                        ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
1051                        ", prog_ids=NULL, prog_cnt=0}",
1052         },
1053         { /* 2 */
1054                 .data = { .BPF_PROG_QUERY_data = {
1055                         .target_fd = 3141592653U,
1056                         .attach_type = 23,
1057                         .query_flags = 0xfffffffe,
1058                         .attach_flags = 0xfffffffc,
1059                         .prog_ids = 0xffffffffffffffffULL,
1060                         .prog_cnt = 2718281828,
1061                 } },
1062                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1063                 .str = "query={target_fd=-1153374643"
1064                        ", attach_type=0x17 /* BPF_??? */"
1065                        ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
1066                        ", attach_flags=0xfffffffc /* BPF_F_??? */"
1067                        ", prog_ids="
1068                        BIG_ADDR("0xffffffffffffffff", "0xffffffff")
1069                        ", prog_cnt=2718281828}",
1070         },
1071         { /* 3 */
1072                 .data = { .BPF_PROG_QUERY_data = {
1073                         .target_fd = 3141592653U,
1074                         .attach_type = 0xfeedface,
1075                         .query_flags = 0xdeadf00d,
1076                         .attach_flags = 0xbeefcafe,
1077                         .prog_ids = 0xffffffffffffffffULL,
1078                         .prog_cnt = 0,
1079                 } },
1080                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1081                 .str = "query={target_fd=-1153374643"
1082                        ", attach_type=0xfeedface /* BPF_??? */"
1083                        ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
1084                        ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
1085                        ", prog_ids=" BIG_ADDR_MAYBE("0xffffffffffffffff") "[]"
1086                        ", prog_cnt=0}",
1087         },
1088         { /* 4 */
1089                 .data = { .BPF_PROG_QUERY_data = {
1090                         .target_fd = 3141592653U,
1091                         .attach_type = 0xfeedface,
1092                         .query_flags = 0xdeadf00d,
1093                         .attach_flags = 0xbeefcafe,
1094                 } },
1095                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1096                 .init_fn = init_BPF_PROG_QUERY_attr4,
1097                 .print_fn = print_BPF_PROG_QUERY_attr4,
1098         },
1099         { /* 5 */
1100                 .data = { .BPF_PROG_QUERY_data = {
1101                         .target_fd = 3141592653U,
1102                         .attach_type = 0xfeedface,
1103                         .query_flags = 0xdeadf00d,
1104                         .attach_flags = 0xbeefcafe,
1105                 } },
1106                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
1107                 .init_fn = init_BPF_PROG_QUERY_attr5,
1108                 .print_fn = print_BPF_PROG_QUERY_attr5,
1109         },
1110 };
1111
1112
1113 static void
1114 init_BPF_RAW_TRACEPOINT_attr2(struct bpf_attr_check *check)
1115 {
1116         /* TODO: test the 128 byte limit */
1117         static const char tp_name[] = "0123456789qwertyuiop0123456789qwe";
1118
1119         struct BPF_RAW_TRACEPOINT_OPEN_struct *attr =
1120                 &check->data.BPF_RAW_TRACEPOINT_OPEN_data;
1121
1122         attr->name = (uintptr_t) tp_name;
1123 }
1124
1125 static struct bpf_attr_check BPF_RAW_TRACEPOINT_OPEN_checks[] = {
1126         {
1127                 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = { .name = 0 } },
1128                 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1129                                     name),
1130                 .str = "raw_tracepoint={name=NULL, prog_fd=0}",
1131         },
1132         { /* 1 */
1133                 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1134                         .name = 0xffffffff00000000ULL,
1135                         .prog_fd = 0xdeadbeef,
1136                 } },
1137                 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1138                                     prog_fd),
1139                 .str = "raw_tracepoint="
1140                        "{name=" BIG_ADDR("0xffffffff00000000", "NULL")
1141                        ", prog_fd=-559038737}",
1142         },
1143         {
1144                 .data = { .BPF_RAW_TRACEPOINT_OPEN_data = {
1145                         .prog_fd = 0xdeadbeef,
1146                 } },
1147                 .size = offsetofend(struct BPF_RAW_TRACEPOINT_OPEN_struct,
1148                                     prog_fd),
1149                 .init_fn = init_BPF_RAW_TRACEPOINT_attr2,
1150                 .str = "raw_tracepoint="
1151                        "{name=\"0123456789qwertyuiop0123456789qw\"..."
1152                        ", prog_fd=-559038737}",
1153         }
1154 };
1155
1156 static void
1157 init_BPF_BTF_LOAD_attr(struct bpf_attr_check *check)
1158 {
1159         static const char sample_btf_data[] = "bPf\0daTum";
1160
1161         static char *btf_data;
1162         if (!btf_data)
1163                 btf_data = tail_memdup(sample_btf_data,
1164                                        sizeof(sample_btf_data) - 1);
1165
1166         struct BPF_BTF_LOAD_struct *attr = &check->data.BPF_BTF_LOAD_data;
1167         attr->btf = (uintptr_t) btf_data;
1168 }
1169
1170 static struct bpf_attr_check BPF_BTF_LOAD_checks[] = {
1171         {
1172                 .data = { .BPF_BTF_LOAD_data = { .btf = 0 } },
1173                 .size = offsetofend(struct BPF_BTF_LOAD_struct, btf),
1174                 .str = "btf=NULL, btf_log_buf=NULL, btf_size=0"
1175                        ", btf_log_size=0, btf_log_level=0"
1176         },
1177         { /* 1 */
1178                 .data = { .BPF_BTF_LOAD_data = {
1179                         .btf_log_buf = 0xfacefeeddeadbeefULL,
1180                         .btf_size = 9,
1181                         .btf_log_size = -1U,
1182                         .btf_log_level = 42
1183                 } },
1184                 .size = offsetofend(struct BPF_BTF_LOAD_struct, btf_log_level),
1185                 .init_fn = init_BPF_BTF_LOAD_attr,
1186                 .str = "btf=\"bPf\\0daTum\""
1187                        ", btf_log_buf=0xfacefeeddeadbeef"
1188                        ", btf_size=9"
1189                        ", btf_log_size=4294967295"
1190                        ", btf_log_level=42"
1191         }
1192 };
1193
1194 static const struct bpf_attr_check BPF_BTF_GET_FD_BY_ID_checks[] = {
1195         {
1196                 .data = { .BPF_BTF_GET_FD_BY_ID_data = { .btf_id = 0xdeadbeef } },
1197                 .size = offsetofend(struct BPF_BTF_GET_FD_BY_ID_struct, btf_id),
1198                 .str = "btf_id=3735928559"
1199         }
1200 };
1201
1202 static const struct bpf_attr_check BPF_TASK_FD_QUERY_checks[] = {
1203         {
1204                 .data = { .BPF_TASK_FD_QUERY_data = { .pid = 0xdeadbeef } },
1205                 .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, pid),
1206                 .str = "task_fd_query={pid=3735928559, fd=0, flags=0"
1207                        ", buf_len=0, buf=NULL, prog_id=0"
1208                        ", fd_type=BPF_FD_TYPE_RAW_TRACEPOINT"
1209                        ", probe_offset=0, probe_addr=0}"
1210         },
1211         { /* 1 */
1212                 .data = { .BPF_TASK_FD_QUERY_data = {
1213                         .pid = 0xcafef00d,
1214                         .fd = 0xdeadbeef,
1215                         .flags = 0xfacefeed,
1216                         .buf_len = 0xdefaced,
1217                         .buf = 0xfffffffffffffffe,
1218                         .prog_id = 0xbadc0ded,
1219                         .fd_type = 5,
1220                         .probe_offset = 0xfac1fed2fac3fed4,
1221                         .probe_addr = 0xfac5fed5fac7fed8
1222                 } },
1223                 .size = offsetofend(struct BPF_TASK_FD_QUERY_struct, probe_addr),
1224                 .str = "task_fd_query={pid=3405705229"
1225                        ", fd=-559038737"
1226                        ", flags=4207869677"
1227                        ", buf_len=233811181"
1228                        ", buf=" BIG_ADDR("0xfffffffffffffffe", "0xfffffffe")
1229                        ", prog_id=3134983661"
1230                        ", fd_type=BPF_FD_TYPE_URETPROBE"
1231                        ", probe_offset=0xfac1fed2fac3fed4"
1232                        ", probe_addr=0xfac5fed5fac7fed8}"
1233         }
1234 };
1235
1236
1237 #define CHK(cmd_) \
1238         { \
1239                 cmd_, #cmd_, \
1240                 cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \
1241         } \
1242         /* End of CHK definition */
1243
1244 int
1245 main(void)
1246 {
1247         static const struct bpf_check checks[] = {
1248                 CHK(BPF_MAP_CREATE),
1249                 CHK(BPF_MAP_LOOKUP_ELEM),
1250                 CHK(BPF_MAP_UPDATE_ELEM),
1251                 CHK(BPF_MAP_DELETE_ELEM),
1252                 CHK(BPF_MAP_GET_NEXT_KEY),
1253                 CHK(BPF_PROG_LOAD),
1254                 CHK(BPF_OBJ_PIN),
1255                 CHK(BPF_OBJ_GET),
1256                 CHK(BPF_PROG_ATTACH),
1257                 CHK(BPF_PROG_DETACH),
1258                 CHK(BPF_PROG_TEST_RUN),
1259                 CHK(BPF_PROG_GET_NEXT_ID),
1260                 CHK(BPF_MAP_GET_NEXT_ID),
1261                 CHK(BPF_PROG_GET_FD_BY_ID),
1262                 CHK(BPF_MAP_GET_FD_BY_ID),
1263                 CHK(BPF_OBJ_GET_INFO_BY_FD),
1264                 CHK(BPF_PROG_QUERY),
1265                 CHK(BPF_RAW_TRACEPOINT_OPEN),
1266                 CHK(BPF_BTF_LOAD),
1267                 CHK(BPF_BTF_GET_FD_BY_ID),
1268                 CHK(BPF_TASK_FD_QUERY),
1269                 CHK(BPF_MAP_LOOKUP_AND_DELETE_ELEM),
1270                 CHK(BPF_MAP_FREEZE),
1271         };
1272
1273         page_size = get_page_size();
1274         end_of_page = (unsigned long) tail_alloc(1) + 1;
1275
1276         for (size_t i = 0; i < ARRAY_SIZE(checks); i++)
1277                 test_bpf(checks + i);
1278
1279         sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL);
1280         printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n",
1281                0xbadc0dedu, errstr);
1282
1283         sys_bpf(0xfacefeed, end_of_page, 40);
1284         printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
1285                end_of_page, errstr);
1286
1287         puts("+++ exited with 0 +++");
1288         return 0;
1289 }