]> granicus.if.org Git - strace/blob - tests/bpf.c
bpf: update BPF_MAP_CREATE decoding
[strace] / tests / bpf.c
1 /*
2  * Check bpf syscall decoding.
3  *
4  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "tests.h"
31 #include <asm/unistd.h>
32
33 #if defined __NR_bpf                            \
34  && (defined HAVE_UNION_BPF_ATTR_ATTACH_FLAGS   \
35   || defined HAVE_UNION_BPF_ATTR_BPF_FD         \
36   || defined HAVE_UNION_BPF_ATTR_FLAGS          \
37   || defined HAVE_UNION_BPF_ATTR_NUMA_NODE      \
38   || defined HAVE_UNION_BPF_ATTR_PROG_FLAGS)
39
40 # include <stddef.h>
41 # include <stdio.h>
42 # include <stdint.h>
43 # include <string.h>
44 # include <unistd.h>
45 # include <linux/bpf.h>
46
47 static const kernel_ulong_t long_bits = (kernel_ulong_t) 0xfacefeed00000000ULL;
48 static const char *errstr;
49 static unsigned int sizeof_attr = sizeof(union bpf_attr);
50 static unsigned int page_size;
51 static unsigned long end_of_page;
52
53 static long
54 sys_bpf(kernel_ulong_t cmd, kernel_ulong_t attr, kernel_ulong_t size)
55 {
56         long rc = syscall(__NR_bpf, cmd, attr, size);
57         errstr = sprintrc(rc);
58         return rc;
59 }
60
61 # if VERBOSE
62 #  define print_extra_data(addr_, size_) print_quoted_hex((addr_), (size_))
63 # else
64 #  define print_extra_data(addr_, size_) printf("...")
65 #endif
66
67 # define TEST_BPF_(cmd_, cmd_str_,                                      \
68                   init_first_, print_first_,                            \
69                   init_attr_, print_attr_)                              \
70         do {                                                            \
71                 /* zero addr */                                         \
72                 sys_bpf(cmd_, 0, long_bits | sizeof(union bpf_attr));   \
73                 printf("bpf(%s, NULL, %u) = %s\n",                      \
74                        cmd_str_, sizeof_attr, errstr);                  \
75                                                                         \
76                 /* zero size */                                         \
77                 unsigned long addr = end_of_page - sizeof_attr;         \
78                 sys_bpf(cmd_, addr, long_bits);                         \
79                 printf("bpf(%s, %#lx, 0) = %s\n",                       \
80                        cmd_str_, addr, errstr);                         \
81                                                                         \
82                 /* the first field only */                              \
83                 unsigned int offset = init_first_(end_of_page);         \
84                 addr = end_of_page - offset;                            \
85                 sys_bpf(cmd_, addr, offset);                            \
86                 printf("bpf(%s, {", cmd_str_);                          \
87                 print_first_(addr);                                     \
88                 printf("}, %u) = %s\n", offset, errstr);                \
89                                                                         \
90                 /* efault after the first field */                      \
91                 sys_bpf(cmd_, addr, offset + 1);                        \
92                 printf("bpf(%s, %#lx, %u) = %s\n",                      \
93                        cmd_str_, addr, offset + 1, errstr);             \
94                                                                         \
95                 /* the relevant part of union bpf_attr */               \
96                 offset = init_attr_(end_of_page);                       \
97                 addr = end_of_page - offset;                            \
98                 sys_bpf(cmd_, addr, offset);                            \
99                 printf("bpf(%s, {", cmd_str_);                          \
100                 print_attr_(addr);                                      \
101                 printf("}, %u) = %s\n", offset, errstr);                \
102                                                                         \
103                 /* short read of the relevant part of union bpf_attr */ \
104                 sys_bpf(cmd_, addr + 1, offset);                        \
105                 printf("bpf(%s, %#lx, %u) = %s\n",                      \
106                        cmd_str_, addr + 1, offset, errstr);             \
107                                                                         \
108                 if (offset < sizeof_attr) {                             \
109                         /* short read of the whole union bpf_attr */    \
110                         memmove((void *) end_of_page - sizeof_attr + 1, \
111                                 (void *) addr, offset);                 \
112                         addr = end_of_page - sizeof_attr + 1;           \
113                         memset((void *) addr + offset, 0,               \
114                                sizeof_attr - offset - 1);               \
115                         sys_bpf(cmd_, addr, sizeof_attr);               \
116                         printf("bpf(%s, %#lx, %u) = %s\n",              \
117                                cmd_str_, addr, sizeof_attr, errstr);    \
118                                                                         \
119                         /* the whole union bpf_attr */                  \
120                         memmove((void *) end_of_page - sizeof_attr,     \
121                                 (void *) addr, offset);                 \
122                         addr = end_of_page - sizeof_attr;               \
123                         memset((void *) addr + offset, 0,               \
124                                sizeof_attr - offset);                   \
125                         sys_bpf(cmd_, addr, sizeof_attr);               \
126                         printf("bpf(%s, {", cmd_str_);                  \
127                         print_attr_(addr);                              \
128                         printf("}, %u) = %s\n", sizeof_attr, errstr);   \
129                                                                         \
130                         /* non-zero bytes after the relevant part */    \
131                         fill_memory_ex((void *) addr + offset,          \
132                                        sizeof_attr - offset, '0', 10);  \
133                         sys_bpf(cmd_, addr, sizeof_attr);               \
134                         printf("bpf(%s, {", cmd_str_);                  \
135                         print_attr_(addr);                              \
136                         printf(", ");                                   \
137                         print_extra_data((void *) addr + offset,        \
138                                          sizeof_attr - offset);         \
139                         printf("}, %u) = %s\n", sizeof_attr, errstr);   \
140                 }                                                       \
141                                                                         \
142                 /* short read of the whole page */                      \
143                 memmove((void *) end_of_page - page_size + 1,           \
144                         (void *) addr, offset);                         \
145                 addr = end_of_page - page_size + 1;                     \
146                 memset((void *) addr + offset, 0,                       \
147                        page_size - offset - 1);                         \
148                 sys_bpf(cmd_, addr, page_size);                         \
149                 printf("bpf(%s, %#lx, %u) = %s\n",                      \
150                        cmd_str_, addr, page_size, errstr);              \
151                                                                         \
152                 /* the whole page */                                    \
153                 memmove((void *) end_of_page - page_size,               \
154                         (void *) addr, offset);                         \
155                 addr = end_of_page - page_size;                         \
156                 memset((void *) addr + offset, 0, page_size - offset);  \
157                 sys_bpf(cmd_, addr, page_size);                         \
158                 printf("bpf(%s, {", cmd_str_);                          \
159                 print_attr_(addr);                                      \
160                 printf("}, %u) = %s\n", page_size, errstr);             \
161                                                                         \
162                 /* non-zero bytes after the whole union bpf_attr */     \
163                 fill_memory_ex((void *) addr + offset,                  \
164                                page_size - offset, '0', 10);            \
165                 sys_bpf(cmd_, addr, page_size);                         \
166                 printf("bpf(%s, {", cmd_str_);                          \
167                 print_attr_(addr);                                      \
168                 printf(", ");                                           \
169                 print_extra_data((void *) addr + offset,                \
170                                  page_size - offset);                   \
171                 printf("}, %u) = %s\n", page_size, errstr);             \
172                                                                         \
173                 /* more than a page */                                  \
174                 sys_bpf(cmd_, addr, page_size + 1);                     \
175                 printf("bpf(%s, %#lx, %u) = %s\n",                      \
176                        cmd_str_, addr, page_size + 1, errstr);          \
177         } while (0)                                                     \
178         /* End of TEST_BPF_ definition. */
179
180 # define TEST_BPF(cmd_)                                                 \
181         TEST_BPF_((cmd_), #cmd_,                                        \
182                   init_ ## cmd_ ## _first, print_ ## cmd_ ## _first,    \
183                   init_ ## cmd_ ## _attr, print_ ## cmd_ ## _attr)      \
184         /* End of TEST_BPF definition. */
185
186 # ifdef HAVE_UNION_BPF_ATTR_NUMA_NODE
187
188 static unsigned int
189 init_BPF_MAP_CREATE_first(const unsigned long eop)
190 {
191         static const union bpf_attr attr = { .map_type = 2 };
192         static const unsigned int offset = sizeof(attr.map_type);
193         const unsigned long addr = eop - offset;
194
195         memcpy((void *) addr, &attr.map_type, offset);
196         return offset;
197 }
198
199 static void
200 print_BPF_MAP_CREATE_first(const unsigned long addr)
201 {
202         printf("map_type=BPF_MAP_TYPE_ARRAY, key_size=0, value_size=0"
203                ", max_entries=0, map_flags=0, inner_map_fd=0");
204 }
205
206 static unsigned int
207 init_BPF_MAP_CREATE_attr(const unsigned long eop)
208 {
209         static const union bpf_attr attr = {
210                 .map_type = 1,
211                 .key_size = 4,
212                 .value_size = 8,
213                 .max_entries = 256,
214                 .map_flags = 7,
215                 .inner_map_fd = -1,
216                 .numa_node = 42
217         };
218         static const unsigned int offset =
219                 offsetofend(union bpf_attr, numa_node);
220         const unsigned long addr = eop - offset;
221
222         memcpy((void *) addr, &attr, offset);
223         return offset;
224 }
225
226 static void
227 print_BPF_MAP_CREATE_attr(const unsigned long addr)
228 {
229         printf("map_type=BPF_MAP_TYPE_HASH, key_size=4"
230                ", value_size=8, max_entries=256"
231                ", map_flags=BPF_F_NO_PREALLOC|BPF_F_NO_COMMON_LRU"
232                "|BPF_F_NUMA_NODE, inner_map_fd=-1, numa_node=42");
233 }
234
235 # endif /* HAVE_UNION_BPF_ATTR_NUMA_NODE */
236
237 # ifdef HAVE_UNION_BPF_ATTR_FLAGS
238
239 static unsigned int
240 init_BPF_MAP_LOOKUP_ELEM_first(const unsigned long eop)
241 {
242         static const union bpf_attr attr = { .map_fd = -1 };
243         static const unsigned int offset = sizeof(attr.map_fd);
244         const unsigned long addr = eop - offset;
245
246         memcpy((void *) addr, &attr.map_fd, offset);
247         return offset;
248 }
249
250 static void
251 print_BPF_MAP_LOOKUP_ELEM_first(const unsigned long addr)
252 {
253         printf("map_fd=-1, key=0, value=0");
254 }
255
256 static unsigned int
257 init_BPF_MAP_LOOKUP_ELEM_attr(const unsigned long eop)
258 {
259         static const union bpf_attr attr = {
260                 .map_fd = -1,
261                 .key = 0xdeadbeef,
262                 .value = 0xbadc0ded
263         };
264         static const unsigned int offset =
265                 offsetofend(union bpf_attr, value);
266         const unsigned long addr = eop - offset;
267
268         memcpy((void *) addr, &attr, offset);
269         return offset;
270 }
271
272 static void
273 print_BPF_MAP_LOOKUP_ELEM_attr(const unsigned long addr)
274 {
275         printf("map_fd=-1, key=0xdeadbeef, value=0xbadc0ded");
276 }
277
278 #  define init_BPF_MAP_UPDATE_ELEM_first init_BPF_MAP_LOOKUP_ELEM_first
279
280 static void
281 print_BPF_MAP_UPDATE_ELEM_first(const unsigned long addr)
282 {
283         printf("map_fd=-1, key=0, value=0, flags=BPF_ANY");
284 }
285
286 static unsigned int
287 init_BPF_MAP_UPDATE_ELEM_attr(const unsigned long eop)
288 {
289         static const union bpf_attr attr = {
290                 .map_fd = -1,
291                 .key = 0xdeadbeef,
292                 .value = 0xbadc0ded,
293                 .flags = 2
294         };
295         static const unsigned int offset =
296                 offsetofend(union bpf_attr, flags);
297         const unsigned long addr = eop - offset;
298
299         memcpy((void *) addr, &attr, offset);
300         return offset;
301 }
302
303 static void
304 print_BPF_MAP_UPDATE_ELEM_attr(const unsigned long addr)
305 {
306         printf("map_fd=-1, key=0xdeadbeef, value=0xbadc0ded, flags=BPF_EXIST");
307 }
308
309 #  define init_BPF_MAP_DELETE_ELEM_first init_BPF_MAP_LOOKUP_ELEM_first
310
311 static void
312 print_BPF_MAP_DELETE_ELEM_first(const unsigned long addr)
313 {
314         printf("map_fd=-1, key=0");
315 }
316
317 static unsigned int
318 init_BPF_MAP_DELETE_ELEM_attr(const unsigned long eop)
319 {
320         static const union bpf_attr attr = {
321                 .map_fd = -1,
322                 .key = 0xdeadbeef
323         };
324         static const unsigned int offset =
325                 offsetofend(union bpf_attr, key);
326         const unsigned long addr = eop - offset;
327
328         memcpy((void *) addr, &attr, offset);
329         return offset;
330 }
331
332 static void
333 print_BPF_MAP_DELETE_ELEM_attr(const unsigned long addr)
334 {
335         printf("map_fd=-1, key=0xdeadbeef");
336 }
337
338 #  define init_BPF_MAP_GET_NEXT_KEY_first init_BPF_MAP_LOOKUP_ELEM_first
339
340 static void
341 print_BPF_MAP_GET_NEXT_KEY_first(const unsigned long addr)
342 {
343         printf("map_fd=-1, key=0, next_key=0");
344 }
345
346 static unsigned int
347 init_BPF_MAP_GET_NEXT_KEY_attr(const unsigned long eop)
348 {
349         static const union bpf_attr attr = {
350                 .map_fd = -1,
351                 .key = 0xdeadbeef,
352                 .next_key = 0xbadc0ded
353         };
354         static const unsigned int offset =
355                 offsetofend(union bpf_attr, next_key);
356         const unsigned long addr = eop - offset;
357
358         memcpy((void *) addr, &attr, offset);
359         return offset;
360 }
361
362 static void
363 print_BPF_MAP_GET_NEXT_KEY_attr(const unsigned long addr)
364 {
365         printf("map_fd=-1, key=0xdeadbeef, next_key=0xbadc0ded");
366 }
367
368 # endif /* HAVE_UNION_BPF_ATTR_FLAGS */
369
370 # ifdef HAVE_UNION_BPF_ATTR_PROG_FLAGS
371
372 static unsigned int
373 init_BPF_PROG_LOAD_first(const unsigned long eop)
374 {
375         static const union bpf_attr attr = { .prog_type = 1 };
376         static const unsigned int offset = sizeof(attr.prog_type);
377         const unsigned long addr = eop - offset;
378
379         memcpy((void *) addr, &attr.prog_type, offset);
380         return offset;
381 }
382
383 static void
384 print_BPF_PROG_LOAD_first(const unsigned long addr)
385 {
386
387         printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=0, insns=0"
388                ", license=NULL, log_level=0, log_size=0, log_buf=0"
389                ", kern_version=0, prog_flags=0");
390 }
391
392 static const struct bpf_insn insns[] = {
393         { .code = BPF_JMP | BPF_EXIT }
394 };
395 static char log_buf[4096];
396
397 static unsigned int
398 init_BPF_PROG_LOAD_attr(const unsigned long eop)
399 {
400         const union bpf_attr attr = {
401                 .prog_type = 1,
402                 .insn_cnt = ARRAY_SIZE(insns),
403                 .insns = (uintptr_t) insns,
404                 .license = (uintptr_t) "GPL",
405                 .log_level = 42,
406                 .log_size = sizeof(log_buf),
407                 .log_buf = (uintptr_t) log_buf,
408                 .kern_version = 0xcafef00d,
409                 .prog_flags = 1
410         };
411         static const unsigned int offset =
412                 offsetofend(union bpf_attr, prog_flags);
413         const unsigned long addr = eop - offset;
414
415         memcpy((void *) addr, &attr, offset);
416         return offset;
417 }
418
419 static void
420 print_BPF_PROG_LOAD_attr(const unsigned long addr)
421 {
422         printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u, insns=%p"
423                ", license=\"GPL\", log_level=42, log_size=4096, log_buf=%p"
424                ", kern_version=%u, prog_flags=BPF_F_STRICT_ALIGNMENT",
425                (unsigned int) ARRAY_SIZE(insns), insns,
426                log_buf, 0xcafef00d);
427 }
428
429 # endif /* HAVE_UNION_BPF_ATTR_PROG_FLAGS */
430
431 /*
432  * bpf() syscall and its first six commands were introduced in Linux kernel
433  * 3.18. Some additional commands were added afterwards, so we need to take
434  * precautions to make sure the tests compile.
435  *
436  * BPF_OBJ_PIN and BPF_OBJ_GET commands appear in kernel 4.4.
437  */
438 # ifdef HAVE_UNION_BPF_ATTR_BPF_FD
439
440 static unsigned int
441 init_BPF_OBJ_PIN_first(const unsigned long eop)
442 {
443         static const union bpf_attr attr = {};
444         static const unsigned int offset = sizeof(attr.pathname);
445         const unsigned long addr = eop - offset;
446
447         memcpy((void *) addr, &attr.pathname, offset);
448         return offset;
449 }
450
451 static void
452 print_BPF_OBJ_PIN_first(const unsigned long addr)
453 {
454
455         printf("pathname=NULL, bpf_fd=0");
456 }
457
458 static unsigned int
459 init_BPF_OBJ_PIN_attr(const unsigned long eop)
460 {
461         const union bpf_attr attr = {
462                 .pathname = (uintptr_t) "/sys/fs/bpf/foo/bar",
463                 .bpf_fd = -1
464         };
465         static const unsigned int offset =
466                 offsetofend(union bpf_attr, bpf_fd);
467         const unsigned long addr = eop - offset;
468
469         memcpy((void *) addr, &attr, offset);
470         return offset;
471 }
472
473 static void
474 print_BPF_OBJ_PIN_attr(const unsigned long addr)
475 {
476         printf("pathname=\"/sys/fs/bpf/foo/bar\", bpf_fd=-1");
477 }
478
479 #  define init_BPF_OBJ_GET_first init_BPF_OBJ_PIN_first
480 #  define print_BPF_OBJ_GET_first print_BPF_OBJ_PIN_first
481 #  define init_BPF_OBJ_GET_attr init_BPF_OBJ_PIN_attr
482 #  define print_BPF_OBJ_GET_attr print_BPF_OBJ_PIN_attr
483
484 # endif /* HAVE_UNION_BPF_ATTR_BPF_FD */
485
486 /* BPF_PROG_ATTACH and BPF_PROG_DETACH commands appear in kernel 4.10. */
487 # ifdef HAVE_UNION_BPF_ATTR_ATTACH_FLAGS
488
489 static unsigned int
490 init_BPF_PROG_ATTACH_first(const unsigned long eop)
491 {
492         static const union bpf_attr attr = { .target_fd = -1 };
493         static const unsigned int offset = sizeof(attr.target_fd);
494         const unsigned long addr = eop - offset;
495
496         memcpy((void *) addr, &attr.target_fd, offset);
497         return offset;
498 }
499
500 static void
501 print_BPF_PROG_ATTACH_first(const unsigned long addr)
502 {
503         printf("target_fd=-1, attach_bpf_fd=0"
504                ", attach_type=BPF_CGROUP_INET_INGRESS, attach_flags=0");
505 }
506
507 static unsigned int
508 init_BPF_PROG_ATTACH_attr(const unsigned long eop)
509 {
510         static const union bpf_attr attr = {
511                 .target_fd = -1,
512                 .attach_bpf_fd = -2,
513                 .attach_type = 2,
514                 .attach_flags = 1
515         };
516         static const unsigned int offset =
517                 offsetofend(union bpf_attr, attach_flags);
518         const unsigned long addr = eop - offset;
519
520         memcpy((void *) addr, &attr, offset);
521         return offset;
522 }
523
524 static void
525 print_BPF_PROG_ATTACH_attr(const unsigned long addr)
526 {
527         printf("target_fd=-1, attach_bpf_fd=-2"
528                ", attach_type=BPF_CGROUP_INET_SOCK_CREATE"
529                ", attach_flags=BPF_F_ALLOW_OVERRIDE");
530 }
531
532 #  define init_BPF_PROG_DETACH_first init_BPF_PROG_ATTACH_first
533
534 static unsigned int
535 init_BPF_PROG_DETACH_attr(const unsigned long eop)
536 {
537         static const union bpf_attr attr = {
538                 .target_fd = -1,
539                 .attach_type = 2
540         };
541         static const unsigned int offset =
542                 offsetofend(union bpf_attr, attach_type);
543         const unsigned long addr = eop - offset;
544
545         memcpy((void *) addr, &attr, offset);
546         return offset;
547 }
548
549
550 static void
551 print_BPF_PROG_DETACH_first(const unsigned long addr)
552 {
553         printf("target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS");
554 }
555
556 static void
557 print_BPF_PROG_DETACH_attr(const unsigned long addr)
558 {
559         printf("target_fd=-1, attach_type=BPF_CGROUP_INET_SOCK_CREATE");
560 }
561
562 # endif /* HAVE_UNION_BPF_ATTR_ATTACH_FLAGS */
563
564 int
565 main(void)
566 {
567         page_size = get_page_size();
568         end_of_page = (unsigned long) tail_alloc(1) + 1;
569
570 # ifdef HAVE_UNION_BPF_ATTR_NUMA_NODE
571         TEST_BPF(BPF_MAP_CREATE);
572 # endif
573
574 # ifdef HAVE_UNION_BPF_ATTR_FLAGS
575         TEST_BPF(BPF_MAP_LOOKUP_ELEM);
576         TEST_BPF(BPF_MAP_UPDATE_ELEM);
577         TEST_BPF(BPF_MAP_DELETE_ELEM);
578         TEST_BPF(BPF_MAP_GET_NEXT_KEY);
579 # endif
580
581 # ifdef HAVE_UNION_BPF_ATTR_PROG_FLAGS
582         TEST_BPF(BPF_PROG_LOAD);
583 # endif
584
585 # ifdef HAVE_UNION_BPF_ATTR_BPF_FD
586         TEST_BPF(BPF_OBJ_PIN);
587         TEST_BPF(BPF_OBJ_GET);
588 # endif
589
590 # ifdef HAVE_UNION_BPF_ATTR_ATTACH_FLAGS
591         TEST_BPF(BPF_PROG_ATTACH);
592         TEST_BPF(BPF_PROG_DETACH);
593 # endif
594
595         sys_bpf(0xfacefeed, end_of_page, 40);
596         printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n",
597                end_of_page, errstr);
598
599         puts("+++ exited with 0 +++");
600         return 0;
601 }
602
603 #else
604
605 SKIP_MAIN_UNDEFINED("__NR_bpf && HAVE_UNION_BPF_ATTR_*")
606
607 #endif