]> granicus.if.org Git - strace/blob - tests/bpf.c
xlat: update bpf_attach_type constants
[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-2018 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "tests.h"
32
33 #include <stddef.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include <asm/unistd.h>
40 #include "scno.h"
41
42 #ifdef HAVE_LINUX_BPF_H
43 # include <linux/bpf.h>
44 #endif
45
46 #include "bpf_attr.h"
47 #include "print_fields.h"
48
49 #include "xlat.h"
50 #include "xlat/bpf_commands.h"
51
52 #ifndef HAVE_STRUCT_BPF_INSN
53 struct bpf_insn {
54         uint8_t code;
55         uint8_t dst_reg:4;
56         uint8_t src_reg:4;
57         int16_t off;
58         int32_t imm;
59 };
60 #endif
61
62 #define BPF_ATTR_DATA_FIELD(cmd_) struct cmd_ ## _struct cmd_ ## _data
63
64 union bpf_attr_data {
65         BPF_ATTR_DATA_FIELD(BPF_MAP_CREATE);
66         BPF_ATTR_DATA_FIELD(BPF_MAP_LOOKUP_ELEM);
67         BPF_ATTR_DATA_FIELD(BPF_MAP_UPDATE_ELEM);
68         BPF_ATTR_DATA_FIELD(BPF_MAP_DELETE_ELEM);
69         BPF_ATTR_DATA_FIELD(BPF_MAP_GET_NEXT_KEY);
70         BPF_ATTR_DATA_FIELD(BPF_PROG_LOAD);
71         BPF_ATTR_DATA_FIELD(BPF_OBJ_PIN);
72         BPF_ATTR_DATA_FIELD(BPF_PROG_ATTACH);
73         BPF_ATTR_DATA_FIELD(BPF_PROG_DETACH);
74         BPF_ATTR_DATA_FIELD(BPF_PROG_TEST_RUN);
75         BPF_ATTR_DATA_FIELD(BPF_PROG_GET_NEXT_ID);
76         BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
77         BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
78         BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
79         BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
80         char char_data[256];
81 };
82
83 struct bpf_attr_check {
84         union bpf_attr_data data;
85         size_t size;
86         const char *str;
87         void (*init_fn)(struct bpf_attr_check *check);
88         void (*print_fn)(const struct bpf_attr_check *check,
89                          unsigned long addr);
90 };
91
92 struct bpf_check {
93         kernel_ulong_t cmd;
94         const char *cmd_str;
95         const struct bpf_attr_check *checks;
96         size_t count;
97 };
98
99 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
100 static const char *errstr;
101 static unsigned int sizeof_attr = sizeof(union bpf_attr_data);
102 static unsigned int page_size;
103 static unsigned long end_of_page;
104
105 static long
106 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
107 {
108         long rc = syscall(__NR_bpf, cmd, attr, size);
109         errstr = sprintrc(rc);
110         return rc;
111 }
112
113 #if VERBOSE
114 # define print_extra_data(addr_, offs_, size_) \
115         do { \
116                 printf("/* bytes %u..%u */ ", (offs_), (size_) + (offs_) - 1); \
117                 print_quoted_hex((addr_) + (offs_), (size_)); \
118         } while (0)
119 #else
120 # define print_extra_data(addr_, offs_, size_) printf("...")
121 #endif
122
123 static void
124 print_bpf_attr(const struct bpf_attr_check *check, unsigned long addr)
125 {
126         if (check->print_fn)
127                 check->print_fn(check, addr);
128         else
129                 printf("%s", check->str);
130 }
131
132 static void
133 test_bpf(const struct bpf_check *cmd_check)
134 {
135         const struct bpf_attr_check *check = 0;
136         const union bpf_attr_data *data = 0;
137         unsigned int offset = 0;
138
139         /* zero addr */
140         sys_bpf(cmd_check->cmd, 0, long_bits | sizeof(union bpf_attr_data));
141         printf("bpf(%s, NULL, %u) = %s\n",
142                cmd_check->cmd_str, sizeof_attr, errstr);
143
144         /* zero size */
145         unsigned long addr = end_of_page - sizeof_attr;
146         sys_bpf(cmd_check->cmd, addr, long_bits);
147         printf("bpf(%s, %#lx, 0) = %s\n",
148                cmd_check->cmd_str, addr, errstr);
149
150         for (size_t i = 0; i < cmd_check->count; i++) {
151                 check = &cmd_check->checks[i];
152                 if (check->init_fn)
153                         check->init_fn((struct bpf_attr_check *) check);
154                 data = &check->data;
155                 offset = check->size;
156
157                 addr = end_of_page - offset;
158                 memcpy((void *) addr, data, offset);
159
160                 /* starting piece of bpf_attr_data */
161                 sys_bpf(cmd_check->cmd, addr, offset);
162                 printf("bpf(%s, {", cmd_check->cmd_str);
163                 print_bpf_attr(check, addr);
164                 printf("}, %u) = %s\n", offset, errstr);
165
166                 /* short read of the starting piece */
167                 sys_bpf(cmd_check->cmd, addr + 1, offset);
168                 printf("bpf(%s, %#lx, %u) = %s\n",
169                        cmd_check->cmd_str, addr + 1, offset, errstr);
170         }
171
172         if (offset < sizeof_attr) {
173                 /* short read of the whole bpf_attr_data */
174                 memcpy((void *) end_of_page - sizeof_attr + 1, data, offset);
175                 addr = end_of_page - sizeof_attr + 1;
176                 memset((void *) addr + offset, 0, sizeof_attr - offset - 1);
177                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
178                 printf("bpf(%s, %#lx, %u) = %s\n",
179                        cmd_check->cmd_str, addr, sizeof_attr, errstr);
180
181                 /* the whole bpf_attr_data */
182                 memcpy((void *) end_of_page - sizeof_attr, data, offset);
183                 addr = end_of_page - sizeof_attr;
184                 memset((void *) addr + offset, 0, sizeof_attr - offset);
185                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
186                 printf("bpf(%s, {", cmd_check->cmd_str);
187                 print_bpf_attr(check, addr);
188                 printf("}, %u) = %s\n", sizeof_attr, errstr);
189
190                 /* non-zero bytes after the relevant part */
191                 fill_memory_ex((void *) addr + offset,
192                                sizeof_attr - offset, '0', 10);
193                 sys_bpf(cmd_check->cmd, addr, sizeof_attr);
194                 printf("bpf(%s, {", cmd_check->cmd_str);
195                 print_bpf_attr(check, addr);
196                 printf(", ");
197                 print_extra_data((char *) addr, offset,
198                                  sizeof_attr - offset);
199                 printf("}, %u) = %s\n", sizeof_attr, errstr);
200         }
201
202         /* short read of the whole page */
203         memcpy((void *) end_of_page - page_size + 1, data, offset);
204         addr = end_of_page - page_size + 1;
205         memset((void *) addr + offset, 0, page_size - offset - 1);
206         sys_bpf(cmd_check->cmd, addr, page_size);
207         printf("bpf(%s, %#lx, %u) = %s\n",
208                cmd_check->cmd_str, addr, page_size, errstr);
209
210         /* the whole page */
211         memcpy((void *) end_of_page - page_size, data, offset);
212         addr = end_of_page - page_size;
213         memset((void *) addr + offset, 0, page_size - offset);
214         sys_bpf(cmd_check->cmd, addr, page_size);
215         printf("bpf(%s, {", cmd_check->cmd_str);
216         print_bpf_attr(check, addr);
217         printf("}, %u) = %s\n", page_size, errstr);
218
219         /* non-zero bytes after the whole bpf_attr_data */
220         fill_memory_ex((void *) addr + offset,
221                        page_size - offset, '0', 10);
222         sys_bpf(cmd_check->cmd, addr, page_size);
223         printf("bpf(%s, {", cmd_check->cmd_str);
224         print_bpf_attr(check, addr);
225         printf(", ");
226         print_extra_data((char *) addr, offset,
227                          page_size - offset);
228         printf("}, %u) = %s\n", page_size, errstr);
229
230         /* more than a page */
231         sys_bpf(cmd_check->cmd, addr, page_size + 1);
232         printf("bpf(%s, %#lx, %u) = %s\n",
233                cmd_check->cmd_str, addr, page_size + 1, errstr);
234 }
235
236 static void
237 init_BPF_MAP_CREATE_attr7(struct bpf_attr_check *check)
238 {
239         struct BPF_MAP_CREATE_struct *attr = &check->data.BPF_MAP_CREATE_data;
240         attr->map_ifindex = ifindex_lo();
241 }
242
243 static struct bpf_attr_check BPF_MAP_CREATE_checks[] = {
244         {
245                 .data = { .BPF_MAP_CREATE_data = { .map_type = 2 } },
246                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_type),
247                 .str = "map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
248                        ", max_entries=0"
249         },
250         { /* 1 */
251                 .data = { .BPF_MAP_CREATE_data = {
252                         .map_type = 16,
253                         .key_size = 4,
254                         .value_size = 8,
255                         .max_entries = 256,
256                         .map_flags = 63,
257                         .inner_map_fd = -1,
258                         .numa_node = 3141592653,
259                         .map_name = "0123456789abcde",
260                 } },
261                 .size = offsetof(struct BPF_MAP_CREATE_struct, map_name) + 8,
262                 .str = "map_type=BPF_MAP_TYPE_CPUMAP, key_size=4"
263                        ", value_size=8, max_entries=256"
264                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
265                                    "|BPF_F_NUMA_NODE|BPF_F_RDONLY|BPF_F_WRONLY"
266                                    "|BPF_F_STACK_BUILD_ID"
267                        ", inner_map_fd=-1"
268                        ", numa_node=3141592653"
269                        ", map_name=\"0123456\"...",
270
271         },
272         { /* 2 */
273                 .data = { .BPF_MAP_CREATE_data = {
274                         .map_type = 17,
275                         .key_size = 0xface1e55,
276                         .value_size = 0xbadc0ded,
277                         .max_entries = 0xbeefcafe,
278                         .map_flags = 0xffffffc0,
279                         .inner_map_fd = 2718281828,
280                         .numa_node = -1,
281                         .map_name = "",
282                         .map_ifindex = 3141592653,
283                 } },
284                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
285                 .str = "map_type=0x11 /* BPF_MAP_TYPE_??? */"
286                        ", key_size=4207812181, value_size=3134983661"
287                        ", max_entries=3203386110"
288                        ", map_flags=0xffffffc0 /* BPF_F_??? */"
289                        ", inner_map_fd=-1576685468"
290                        ", map_name=\"\", map_ifindex=3141592653",
291
292         },
293         { /* 3 */
294                 .data = { .BPF_MAP_CREATE_data = {
295                         .map_type = 0xdeadf00d,
296                         .key_size = 0xface1e55,
297                         .value_size = 0xbadc0ded,
298                         .max_entries = 0xbeefcafe,
299                         .map_flags = 0xc0dedead,
300                         .inner_map_fd = 2718281828,
301                         .numa_node = -1,
302                 } },
303                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_flags),
304                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
305                        ", key_size=4207812181, value_size=3134983661"
306                        ", max_entries=3203386110"
307                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
308                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
309                                    "|0xc0dede80",
310         },
311         { /* 4 */
312                 .data = { .BPF_MAP_CREATE_data = {
313                         .map_type = 0xdeadf00d,
314                         .key_size = 0xface1e55,
315                         .value_size = 0xbadc0ded,
316                         .max_entries = 0xbeefcafe,
317                         .map_flags = 0xc0dedead,
318                         .inner_map_fd = 2718281828,
319                         .numa_node = -1,
320                 } },
321                 .size = offsetofend(struct BPF_MAP_CREATE_struct, inner_map_fd),
322                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
323                        ", key_size=4207812181, value_size=3134983661"
324                        ", max_entries=3203386110"
325                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
326                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
327                                    "|0xc0dede80"
328                        ", inner_map_fd=-1576685468",
329         },
330         { /* 5 */
331                 .data = { .BPF_MAP_CREATE_data = {
332                         .map_type = 0xdeadf00d,
333                         .key_size = 0xface1e55,
334                         .value_size = 0xbadc0ded,
335                         .max_entries = 0xbeefcafe,
336                         .map_flags = 0xc0dedead,
337                         .inner_map_fd = 2718281828,
338                         .numa_node = -1,
339                 } },
340                 .size = offsetofend(struct BPF_MAP_CREATE_struct, numa_node),
341                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
342                        ", key_size=4207812181, value_size=3134983661"
343                        ", max_entries=3203386110"
344                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
345                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
346                                    "|0xc0dede80"
347                        ", inner_map_fd=-1576685468"
348                        ", numa_node=4294967295 /* NUMA_NO_NODE */",
349         },
350         { /* 6 */
351                 .data = { .BPF_MAP_CREATE_data = {
352                         .map_type = 0xdeadf00d,
353                         .key_size = 0xface1e55,
354                         .value_size = 0xbadc0ded,
355                         .max_entries = 0xbeefcafe,
356                         .map_flags = 0xc0dedead,
357                         .inner_map_fd = 2718281828,
358                         .numa_node = -1,
359                         .map_name = "fedcba9876543210",
360                 } },
361                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_name),
362                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
363                        ", key_size=4207812181, value_size=3134983661"
364                        ", max_entries=3203386110"
365                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
366                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
367                                    "|0xc0dede80"
368                        ", inner_map_fd=-1576685468"
369                        ", numa_node=4294967295 /* NUMA_NO_NODE */"
370                        ", map_name=\"fedcba987654321\"...",
371         },
372         { /* 7 */
373                 .data = { .BPF_MAP_CREATE_data = {
374                         .map_type = 0xdeadf00d,
375                         .key_size = 0xface1e55,
376                         .value_size = 0xbadc0ded,
377                         .max_entries = 0xbeefcafe,
378                         .map_flags = 0xc0dedead,
379                         .inner_map_fd = 2718281828,
380                         .numa_node = -1,
381                         .map_name = "0123456789abcde",
382                 } },
383                 .size = offsetofend(struct BPF_MAP_CREATE_struct, map_ifindex),
384                 .str = "map_type=0xdeadf00d /* BPF_MAP_TYPE_??? */"
385                        ", key_size=4207812181, value_size=3134983661"
386                        ", max_entries=3203386110"
387                        ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NUMA_NODE"
388                                    "|BPF_F_RDONLY|BPF_F_STACK_BUILD_ID"
389                                    "|0xc0dede80"
390                        ", inner_map_fd=-1576685468"
391                        ", numa_node=4294967295 /* NUMA_NO_NODE */"
392                        ", map_name=\"0123456789abcde\""
393                        ", map_ifindex=" IFINDEX_LO_STR,
394                 .init_fn = init_BPF_MAP_CREATE_attr7,
395         },
396 };
397
398 static const struct bpf_attr_check BPF_MAP_LOOKUP_ELEM_checks[] = {
399         {
400                 .data = { .BPF_MAP_LOOKUP_ELEM_data = { .map_fd = -1 } },
401                 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, map_fd),
402                 .str = "map_fd=-1, key=NULL, value=NULL"
403         },
404         {
405                 .data = { .BPF_MAP_LOOKUP_ELEM_data = {
406                         .map_fd = -1,
407                         .key = 0xdeadbeef,
408                         .value = 0xbadc0ded
409                 } },
410                 .size = offsetofend(struct BPF_MAP_LOOKUP_ELEM_struct, value),
411                 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
412         }
413 };
414
415 static const struct bpf_attr_check BPF_MAP_UPDATE_ELEM_checks[] = {
416         {
417                 .data = { .BPF_MAP_UPDATE_ELEM_data = { .map_fd = -1 } },
418                 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, map_fd),
419                 .str = "map_fd=-1, key=NULL, value=NULL, flags=BPF_ANY"
420         },
421         {
422                 .data = { .BPF_MAP_UPDATE_ELEM_data = {
423                         .map_fd = -1,
424                         .key = 0xdeadbeef,
425                         .value = 0xbadc0ded,
426                         .flags = 2
427                 } },
428                 .size = offsetofend(struct BPF_MAP_UPDATE_ELEM_struct, flags),
429                 .str = "map_fd=-1, key=0xdeadbeef, value=0xbadc0ded"
430                        ", flags=BPF_EXIST"
431         }
432 };
433
434 static const struct bpf_attr_check BPF_MAP_DELETE_ELEM_checks[] = {
435         {
436                 .data = { .BPF_MAP_DELETE_ELEM_data = { .map_fd = -1 } },
437                 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, map_fd),
438                 .str = "map_fd=-1, key=NULL"
439         },
440         {
441                 .data = { .BPF_MAP_DELETE_ELEM_data = {
442                         .map_fd = -1,
443                         .key = 0xdeadbeef
444                 } },
445                 .size = offsetofend(struct BPF_MAP_DELETE_ELEM_struct, key),
446                 .str = "map_fd=-1, key=0xdeadbeef"
447         }
448 };
449
450 static const struct bpf_attr_check BPF_MAP_GET_NEXT_KEY_checks[] = {
451         {
452                 .data = { .BPF_MAP_GET_NEXT_KEY_data = { .map_fd = -1 } },
453                 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, map_fd),
454                 .str = "map_fd=-1, key=NULL, next_key=NULL"
455         },
456         {
457                 .data = { .BPF_MAP_GET_NEXT_KEY_data = {
458                         .map_fd = -1,
459                         .key = 0xdeadbeef,
460                         .next_key = 0xbadc0ded
461                 } },
462                 .size = offsetofend(struct BPF_MAP_GET_NEXT_KEY_struct, next_key),
463                 .str = "map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded"
464         }
465 };
466
467 static const struct bpf_insn insns[] = {
468         { .code = 0x95 }
469 };
470 static const char license[] = "GPL";
471 static char log_buf[4096];
472 static const char pathname[] = "/sys/fs/bpf/foo/bar";
473
474 static void
475 init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check)
476 {
477         struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
478         attr->insns = (uintptr_t) insns;
479         attr->license = (uintptr_t) license;
480         attr->log_buf = (uintptr_t) log_buf;
481 }
482
483 static void
484 print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr)
485 {
486         printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u, insns=%p"
487                ", license=\"%s\", log_level=2718281828, log_size=4096"
488                ", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
489                ", prog_flags=0x2 /* BPF_F_??? */"
490                ", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
491                (unsigned int) ARRAY_SIZE(insns), insns,
492                license, log_buf);
493 }
494
495 static void
496 init_BPF_PROG_LOAD_attr4(struct bpf_attr_check *check)
497 {
498         struct BPF_PROG_LOAD_struct *attr = &check->data.BPF_PROG_LOAD_data;
499         attr->insns = (uintptr_t) insns;
500         attr->license = (uintptr_t) license;
501         attr->log_buf = (uintptr_t) log_buf;
502         attr->prog_ifindex = ifindex_lo();
503 }
504
505 static void
506 print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr)
507 {
508         printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=%p"
509                ", license=\"%s\", log_level=2718281828, log_size=4096"
510                ", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
511                ", prog_flags=BPF_F_STRICT_ALIGNMENT|0x2"
512                ", prog_name=\"0123456789abcde\"..., prog_ifindex=%s",
513                (unsigned int) ARRAY_SIZE(insns), insns,
514                license, log_buf, IFINDEX_LO_STR);
515 }
516
517 static struct bpf_attr_check BPF_PROG_LOAD_checks[] = {
518         {
519                 .data = { .BPF_PROG_LOAD_data = { .prog_type = 1 } },
520                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_type),
521                 .str = "prog_type=BPF_PROG_TYPE_SOCKET_FILTER"
522                        ", insn_cnt=0, insns=NULL, license=NULL"
523         },
524         { /* 1 */
525                 .data = { .BPF_PROG_LOAD_data = {
526                         .prog_type = 16,
527                         .insn_cnt = 0xbadc0ded,
528                         .insns = 0,
529                         .license = 0,
530                         .log_level = 42,
531                         .log_size = 3141592653U,
532                         .log_buf = 0,
533                         .kern_version = 0xcafef00d,
534                         .prog_flags = 0,
535                 } },
536                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_flags),
537                 .str = "prog_type=0x10 /* BPF_PROG_TYPE_??? */"
538                        ", insn_cnt=3134983661, insns=NULL, license=NULL"
539                        ", log_level=42, log_size=3141592653, log_buf=NULL"
540                        ", kern_version=KERNEL_VERSION(51966, 240, 13)"
541                        ", prog_flags=0",
542         },
543         { /* 2 */
544                 .data = { .BPF_PROG_LOAD_data = {
545                         .prog_type = 15,
546                         .insn_cnt = 0xbadc0ded,
547                         .insns = 0xffffffff00000000,
548                         .license = 0xffffffff00000000,
549                         .log_level = 2718281828U,
550                         .log_size = sizeof(log_buf),
551                         .log_buf = 0xffffffff00000000,
552                         .kern_version = 0xcafef00d,
553                         .prog_flags = 1,
554                         .prog_name = "fedcba987654321",
555                 } },
556                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
557                 .str = "prog_type=BPF_PROG_TYPE_CGROUP_DEVICE"
558                        ", insn_cnt=3134983661, insns=0xffffffff00000000"
559 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
560                        ", license=0xffffffff00000000"
561 #elif defined __arm__ || defined __i386__ || defined __mips__ || \
562       defined __powerpc__ || defined __riscv__ || defined __s390__ \
563       || defined __sparc__ || defined __tile__
564                        ", license=0xffffffff00000000 or NULL"
565 #else
566                        ", license=NULL"
567 #endif
568                        ", log_level=2718281828, log_size=4096"
569                        ", log_buf=0xffffffff00000000"
570                        ", kern_version=KERNEL_VERSION(51966, 240, 13)"
571                        ", prog_flags=BPF_F_STRICT_ALIGNMENT"
572                        ", prog_name=\"fedcba987654321\"",
573         },
574         { /* 3 */
575                 .data = { .BPF_PROG_LOAD_data = {
576                         .prog_type = 1,
577                         .insn_cnt = ARRAY_SIZE(insns),
578                         .log_level = 2718281828U,
579                         .log_size = sizeof(log_buf),
580                         .kern_version = 0xcafef00d,
581                         .prog_flags = 2,
582                         .prog_name = "0123456789abcdef",
583                         .prog_ifindex = 0xbeeffeed,
584                 } },
585                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
586                 .init_fn = init_BPF_PROG_LOAD_attr3,
587                 .print_fn = print_BPF_PROG_LOAD_attr3
588         },
589         { /* 4 */
590                 .data = { .BPF_PROG_LOAD_data = {
591                         .prog_type = 0,
592                         .insn_cnt = ARRAY_SIZE(insns),
593                         .log_level = 2718281828U,
594                         .log_size = sizeof(log_buf),
595                         .kern_version = 0xcafef00d,
596                         .prog_flags = 3,
597                         .prog_name = "0123456789abcdef",
598                 } },
599                 .size = offsetofend(struct BPF_PROG_LOAD_struct, prog_ifindex),
600                 .init_fn = init_BPF_PROG_LOAD_attr4,
601                 .print_fn = print_BPF_PROG_LOAD_attr4
602         },
603 };
604
605 static void
606 init_BPF_OBJ_PIN_attr(struct bpf_attr_check *check)
607 {
608         struct BPF_OBJ_PIN_struct *attr = &check->data.BPF_OBJ_PIN_data;
609         attr->pathname = (uintptr_t) pathname;
610 }
611
612 static struct bpf_attr_check BPF_OBJ_PIN_checks[] = {
613         {
614                 .data = { .BPF_OBJ_PIN_data = { .pathname = 0 } },
615                 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
616                 .str = "pathname=NULL, bpf_fd=0"
617         },
618         {
619                 .data = { .BPF_OBJ_PIN_data = {
620                         .pathname = 0xFFFFFFFFFFFFFFFFULL
621                 } },
622                 .size = offsetofend(struct BPF_OBJ_PIN_struct, pathname),
623                 .str = "pathname="
624 #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4
625                        "0xffffffffffffffff"
626 #elif defined __arm__ || defined __i386__ || defined __mips__ || \
627       defined __powerpc__ || defined __riscv__ || defined __s390__ \
628       || defined __sparc__ || defined __tile__
629                        "0xffffffffffffffff or 0xffffffff"
630 #else
631                        "0xffffffff"
632 #endif
633                        ", bpf_fd=0",
634         },
635         {
636                 .data = { .BPF_OBJ_PIN_data = { .bpf_fd = -1 } },
637                 .size = offsetofend(struct BPF_OBJ_PIN_struct, bpf_fd),
638                 .init_fn = init_BPF_OBJ_PIN_attr,
639                 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
640         },
641         {
642                 .data = { .BPF_OBJ_PIN_data = {
643                         .bpf_fd = -1,
644                         .file_flags = 0x18
645                 } },
646                 .size = offsetofend(struct BPF_OBJ_PIN_struct, file_flags),
647                 .init_fn = init_BPF_OBJ_PIN_attr,
648                 .str = "pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1"
649                        ", file_flags=BPF_F_RDONLY|BPF_F_WRONLY"
650         }
651 };
652
653 #define BPF_OBJ_GET_checks BPF_OBJ_PIN_checks
654
655 static const struct bpf_attr_check BPF_PROG_ATTACH_checks[] = {
656         {
657                 .data = { .BPF_PROG_ATTACH_data = { .target_fd = -1 } },
658                 .size = offsetofend(struct BPF_PROG_ATTACH_struct, target_fd),
659                 .str = "target_fd=-1, attach_bpf_fd=0"
660                        ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0"
661         },
662         {
663                 .data = { .BPF_PROG_ATTACH_data = {
664                         .target_fd = -1,
665                         .attach_bpf_fd = -2,
666                         .attach_type = 2,
667                         .attach_flags = 1
668                 } },
669                 .size = offsetofend(struct BPF_PROG_ATTACH_struct, attach_flags),
670                 .str = "target_fd=-1, attach_bpf_fd=-2"
671                        ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
672                        ", attach_flags=BPF_F_ALLOW_OVERRIDE"
673         }
674 };
675
676
677 static const struct bpf_attr_check BPF_PROG_DETACH_checks[] = {
678         {
679                 .data = { .BPF_PROG_DETACH_data = { .target_fd = -1 } },
680                 .size = offsetofend(struct BPF_PROG_DETACH_struct, target_fd),
681                 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS"
682         },
683         {
684                 .data = { .BPF_PROG_DETACH_data = {
685                         .target_fd = -1,
686                         .attach_type = 2
687                 } },
688                 .size = offsetofend(struct BPF_PROG_DETACH_struct, attach_type),
689                 .str = "target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE"
690         }
691 };
692
693 static const struct bpf_attr_check BPF_PROG_TEST_RUN_checks[] = {
694         {
695                 .data = { .BPF_PROG_TEST_RUN_data = { .prog_fd = -1 } },
696                 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, prog_fd),
697                 .str = "test={prog_fd=-1, retval=0, data_size_in=0"
698                        ", data_size_out=0, data_in=NULL, data_out=NULL"
699                        ", repeat=0, duration=0}"
700         },
701         {
702                 .data = { .BPF_PROG_TEST_RUN_data = {
703                         .prog_fd = -1,
704                         .retval = 0xfac1fed2,
705                         .data_size_in = 0xfac3fed4,
706                         .data_size_out = 0xfac5fed6,
707                         .data_in = (uint64_t) 0xfacef11dbadc2dedULL,
708                         .data_out = (uint64_t) 0xfacef33dbadc4dedULL,
709                         .repeat = 0xfac7fed8,
710                         .duration = 0xfac9feda
711                 } },
712                 .size = offsetofend(struct BPF_PROG_TEST_RUN_struct, duration),
713                 .str = "test={prog_fd=-1, retval=4207017682"
714                        ", data_size_in=4207148756, data_size_out=4207279830"
715                        ", data_in=0xfacef11dbadc2ded"
716                        ", data_out=0xfacef33dbadc4ded"
717                        ", repeat=4207410904, duration=4207541978}"
718         }
719 };
720
721 static const struct bpf_attr_check BPF_PROG_GET_NEXT_ID_checks[] = {
722         {
723                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
724                         .start_id = 0xdeadbeef
725                 } },
726                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, start_id),
727                 .str = "start_id=3735928559, next_id=0"
728         },
729         {
730                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
731                         .start_id = 0xdeadbeef
732                 } },
733                 .size = 1,
734                 .str = "start_id="
735 #if WORDS_BIGENDIAN
736                        "3724541952"     /* 0xde000000 */
737 #else
738                        "239"            /* 0x000000ef */
739 #endif
740                        ", next_id=0"
741         },
742         {
743                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
744                         .start_id = 0xbadc0ded,
745                         .next_id = 0xcafef00d
746                 } },
747                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, next_id),
748                 .str = "start_id=3134983661, next_id=3405705229"
749         },
750         {
751                 .data = { .BPF_PROG_GET_NEXT_ID_data = {
752                         .start_id = 0xbadc0ded,
753                         .next_id = 0xcafef00d,
754                         .open_flags = 0xffffff27
755                 } },
756                 .size = offsetofend(struct BPF_PROG_GET_NEXT_ID_struct, open_flags),
757                 .str = "start_id=3134983661, next_id=3405705229"
758                        ", open_flags=0xffffff27 /* BPF_F_??? */"
759         }
760 };
761
762 #define BPF_MAP_GET_NEXT_ID_checks BPF_PROG_GET_NEXT_ID_checks
763
764 static const struct bpf_attr_check BPF_PROG_GET_FD_BY_ID_checks[] = {
765         {
766                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
767                         .prog_id = 0xdeadbeef
768                 } },
769                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, prog_id),
770                 .str = "prog_id=3735928559, next_id=0"
771         },
772         {
773                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
774                         .prog_id = 0xbadc0ded,
775                         .next_id = 0xcafef00d
776                 } },
777                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, next_id),
778                 .str = "prog_id=3134983661, next_id=3405705229"
779         },
780         {
781                 .data = { .BPF_PROG_GET_FD_BY_ID_data = {
782                         .prog_id = 0xbadc0ded,
783                         .next_id = 0xcafef00d,
784                         .open_flags = 0xffffff27
785                 } },
786                 .size = offsetofend(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags),
787                 .str = "prog_id=3134983661, next_id=3405705229"
788                        ", open_flags=0xffffff27 /* BPF_F_??? */"
789         }
790 };
791
792 static const struct bpf_attr_check BPF_MAP_GET_FD_BY_ID_checks[] = {
793         {
794                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
795                         .map_id = 0xdeadbeef
796                 } },
797                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, map_id),
798                 .str = "map_id=3735928559, next_id=0"
799         },
800         {
801                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
802                         .map_id = 0xbadc0ded,
803                         .next_id = 0xcafef00d
804                 } },
805                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, next_id),
806                 .str = "map_id=3134983661, next_id=3405705229"
807         },
808         {
809                 .data = { .BPF_MAP_GET_FD_BY_ID_data = {
810                         .map_id = 0xbadc0ded,
811                         .next_id = 0xcafef00d,
812                         .open_flags = 0xffffff27
813                 } },
814                 .size = offsetofend(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags),
815                 .str = "map_id=3134983661, next_id=3405705229"
816                        ", open_flags=0xffffff27 /* BPF_F_??? */"
817         }
818 };
819
820 static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
821         {
822                 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = { .bpf_fd = -1 } },
823                 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, bpf_fd),
824                 .str = "info={bpf_fd=-1, info_len=0, info=0}"
825         },
826         {
827                 .data = { .BPF_OBJ_GET_INFO_BY_FD_data = {
828                         .bpf_fd = -1,
829                         .info_len = 0xdeadbeef,
830                         .info = (uint64_t) 0xfacefeedbadc0dedULL
831                 } },
832                 .size = offsetofend(struct BPF_OBJ_GET_INFO_BY_FD_struct, info),
833                 .str = "info={bpf_fd=-1, info_len=3735928559"
834                        ", info=0xfacefeedbadc0ded}"
835         }
836 };
837
838
839 /* TODO: This is a read/write cmd and we do not check exiting path yet */
840 static const struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
841         {
842                 .data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
843                 .size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
844                 .str = "query={target_fd=-1"
845                        ", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
846                        ", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
847         },
848         { /* 1 */
849                 .data = { .BPF_PROG_QUERY_data = {
850                         .target_fd = 3141592653U,
851                         .attach_type = 13,
852                         .query_flags = 1,
853                         .attach_flags = 3,
854                 } },
855                 .size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
856                 .str = "query={target_fd=-1153374643"
857                        ", attach_type=BPF_CGROUP_INET6_POST_BIND"
858                        ", query_flags=BPF_F_QUERY_EFFECTIVE"
859                        ", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
860                        ", prog_ids=NULL, prog_cnt=0}",
861         },
862         { /* 2 */
863                 .data = { .BPF_PROG_QUERY_data = {
864                         .target_fd = 3141592653U,
865                         .attach_type = 14,
866                         .query_flags = 0xfffffffe,
867                         .attach_flags = 0xfffffffc,
868                         .prog_ids = 0xffffffffffffffffULL,
869                         .prog_cnt = 2718281828,
870                 } },
871                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
872                 .str = "query={target_fd=-1153374643"
873                        ", attach_type=0xe /* BPF_??? */"
874                        ", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
875                        ", attach_flags=0xfffffffc /* BPF_F_??? */"
876                        ", prog_ids=0xffffffffffffffff, prog_cnt=2718281828}",
877         },
878         { /* 3 */
879                 .data = { .BPF_PROG_QUERY_data = {
880                         .target_fd = 3141592653U,
881                         .attach_type = 0xfeedface,
882                         .query_flags = 0xdeadf00d,
883                         .attach_flags = 0xbeefcafe,
884                         .prog_ids = 0xffffffffffffffffULL,
885                         .prog_cnt = 0,
886                 } },
887                 .size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
888                 .str = "query={target_fd=-1153374643"
889                        ", attach_type=0xfeedface /* BPF_??? */"
890                        ", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
891                        ", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
892                        ", prog_ids=0xffffffffffffffff, prog_cnt=0}",
893         },
894 };
895
896
897 #define CHK(cmd_) \
898         { \
899                 cmd_, #cmd_, \
900                 cmd_##_checks, ARRAY_SIZE(cmd_##_checks), \
901         } \
902         /* End of CHK definition */
903
904 int
905 main(void)
906 {
907         static const struct bpf_check checks[] = {
908                 CHK(BPF_MAP_CREATE),
909                 CHK(BPF_MAP_LOOKUP_ELEM),
910                 CHK(BPF_MAP_UPDATE_ELEM),
911                 CHK(BPF_MAP_DELETE_ELEM),
912                 CHK(BPF_MAP_GET_NEXT_KEY),
913                 CHK(BPF_PROG_LOAD),
914                 CHK(BPF_OBJ_PIN),
915                 CHK(BPF_OBJ_GET),
916                 CHK(BPF_PROG_ATTACH),
917                 CHK(BPF_PROG_DETACH),
918                 CHK(BPF_PROG_TEST_RUN),
919                 CHK(BPF_PROG_GET_NEXT_ID),
920                 CHK(BPF_MAP_GET_NEXT_ID),
921                 CHK(BPF_PROG_GET_FD_BY_ID),
922                 CHK(BPF_MAP_GET_FD_BY_ID),
923                 CHK(BPF_OBJ_GET_INFO_BY_FD),
924                 CHK(BPF_PROG_QUERY),
925         };
926
927         page_size = get_page_size();
928         end_of_page = (unsigned long) tail_alloc(1) + 1;
929
930         for (size_t i = 0; i < ARRAY_SIZE(checks); i++)
931                 test_bpf(checks + i);
932
933         sys_bpf(0xfacefeed, 0, (kernel_ulong_t) 0xfacefeedbadc0dedULL);
934         printf("bpf(0xfacefeed /* BPF_??? */, NULL, %u) = %s\n",
935                0xbadc0dedu, errstr);
936
937         sys_bpf(0xfacefeed, end_of_page, 40);
938         printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
939                end_of_page, errstr);
940
941         puts("+++ exited with 0 +++");
942         return 0;
943 }