1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#define _GNU_SOURCE
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <unistd.h>
9
10#include <arpa/inet.h>
11#include <netinet/in.h>
12#include <sys/types.h>
13#include <sys/select.h>
14#include <sys/socket.h>
15
16#include <linux/filter.h>
17
18#include <bpf/bpf.h>
19#include <bpf/libbpf.h>
20
21#include "cgroup_helpers.h"
22#include "testing_helpers.h"
23#include "bpf_util.h"
24
25#ifndef ENOTSUPP
26# define ENOTSUPP 524
27#endif
28
29#define CG_PATH "/foo"
30#define CONNECT4_PROG_PATH "./connect4_prog.bpf.o"
31#define CONNECT6_PROG_PATH "./connect6_prog.bpf.o"
32#define SENDMSG4_PROG_PATH "./sendmsg4_prog.bpf.o"
33#define SENDMSG6_PROG_PATH "./sendmsg6_prog.bpf.o"
34#define RECVMSG4_PROG_PATH "./recvmsg4_prog.bpf.o"
35#define RECVMSG6_PROG_PATH "./recvmsg6_prog.bpf.o"
36#define BIND4_PROG_PATH "./bind4_prog.bpf.o"
37#define BIND6_PROG_PATH "./bind6_prog.bpf.o"
38
39#define SERV4_IP "192.168.1.254"
40#define SERV4_REWRITE_IP "127.0.0.1"
41#define SRC4_IP "172.16.0.1"
42#define SRC4_REWRITE_IP "127.0.0.4"
43#define SERV4_PORT 4040
44#define SERV4_REWRITE_PORT 4444
45
46#define SERV6_IP "face:b00c:1234:5678::abcd"
47#define SERV6_REWRITE_IP "::1"
48#define SERV6_V4MAPPED_IP "::ffff:192.168.0.4"
49#define SRC6_IP "::1"
50#define SRC6_REWRITE_IP "::6"
51#define WILDCARD6_IP "::"
52#define SERV6_PORT 6060
53#define SERV6_REWRITE_PORT 6666
54
55#define INET_NTOP_BUF 40
56
57struct sock_addr_test;
58
59typedef int (*load_fn)(const struct sock_addr_test *test);
60typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
61
62char bpf_log_buf[BPF_LOG_BUF_SIZE];
63
64struct sock_addr_test {
65 const char *descr;
66 /* BPF prog properties */
67 load_fn loadfn;
68 enum bpf_attach_type expected_attach_type;
69 enum bpf_attach_type attach_type;
70 /* Socket properties */
71 int domain;
72 int type;
73 /* IP:port pairs for BPF prog to override */
74 const char *requested_ip;
75 unsigned short requested_port;
76 const char *expected_ip;
77 unsigned short expected_port;
78 const char *expected_src_ip;
79 /* Expected test result */
80 enum {
81 LOAD_REJECT,
82 ATTACH_REJECT,
83 ATTACH_OKAY,
84 SYSCALL_EPERM,
85 SYSCALL_ENOTSUPP,
86 SUCCESS,
87 } expected_result;
88};
89
90static int bind4_prog_load(const struct sock_addr_test *test);
91static int bind6_prog_load(const struct sock_addr_test *test);
92static int connect4_prog_load(const struct sock_addr_test *test);
93static int connect6_prog_load(const struct sock_addr_test *test);
94static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
95static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
96static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
97static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
98static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
99static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test);
100static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
101static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
102static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
103static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
104static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
105static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
106
107static struct sock_addr_test tests[] = {
108 /* bind */
109 {
110 "bind4: load prog with wrong expected attach type",
111 bind4_prog_load,
112 BPF_CGROUP_INET6_BIND,
113 BPF_CGROUP_INET4_BIND,
114 AF_INET,
115 SOCK_STREAM,
116 NULL,
117 0,
118 NULL,
119 0,
120 NULL,
121 LOAD_REJECT,
122 },
123 {
124 "bind4: attach prog with wrong attach type",
125 bind4_prog_load,
126 BPF_CGROUP_INET4_BIND,
127 BPF_CGROUP_INET6_BIND,
128 AF_INET,
129 SOCK_STREAM,
130 NULL,
131 0,
132 NULL,
133 0,
134 NULL,
135 ATTACH_REJECT,
136 },
137 {
138 "bind4: rewrite IP & TCP port in",
139 bind4_prog_load,
140 BPF_CGROUP_INET4_BIND,
141 BPF_CGROUP_INET4_BIND,
142 AF_INET,
143 SOCK_STREAM,
144 SERV4_IP,
145 SERV4_PORT,
146 SERV4_REWRITE_IP,
147 SERV4_REWRITE_PORT,
148 NULL,
149 SUCCESS,
150 },
151 {
152 "bind4: rewrite IP & UDP port in",
153 bind4_prog_load,
154 BPF_CGROUP_INET4_BIND,
155 BPF_CGROUP_INET4_BIND,
156 AF_INET,
157 SOCK_DGRAM,
158 SERV4_IP,
159 SERV4_PORT,
160 SERV4_REWRITE_IP,
161 SERV4_REWRITE_PORT,
162 NULL,
163 SUCCESS,
164 },
165 {
166 "bind6: load prog with wrong expected attach type",
167 bind6_prog_load,
168 BPF_CGROUP_INET4_BIND,
169 BPF_CGROUP_INET6_BIND,
170 AF_INET6,
171 SOCK_STREAM,
172 NULL,
173 0,
174 NULL,
175 0,
176 NULL,
177 LOAD_REJECT,
178 },
179 {
180 "bind6: attach prog with wrong attach type",
181 bind6_prog_load,
182 BPF_CGROUP_INET6_BIND,
183 BPF_CGROUP_INET4_BIND,
184 AF_INET,
185 SOCK_STREAM,
186 NULL,
187 0,
188 NULL,
189 0,
190 NULL,
191 ATTACH_REJECT,
192 },
193 {
194 "bind6: rewrite IP & TCP port in",
195 bind6_prog_load,
196 BPF_CGROUP_INET6_BIND,
197 BPF_CGROUP_INET6_BIND,
198 AF_INET6,
199 SOCK_STREAM,
200 SERV6_IP,
201 SERV6_PORT,
202 SERV6_REWRITE_IP,
203 SERV6_REWRITE_PORT,
204 NULL,
205 SUCCESS,
206 },
207 {
208 "bind6: rewrite IP & UDP port in",
209 bind6_prog_load,
210 BPF_CGROUP_INET6_BIND,
211 BPF_CGROUP_INET6_BIND,
212 AF_INET6,
213 SOCK_DGRAM,
214 SERV6_IP,
215 SERV6_PORT,
216 SERV6_REWRITE_IP,
217 SERV6_REWRITE_PORT,
218 NULL,
219 SUCCESS,
220 },
221
222 /* connect */
223 {
224 "connect4: load prog with wrong expected attach type",
225 connect4_prog_load,
226 BPF_CGROUP_INET6_CONNECT,
227 BPF_CGROUP_INET4_CONNECT,
228 AF_INET,
229 SOCK_STREAM,
230 NULL,
231 0,
232 NULL,
233 0,
234 NULL,
235 LOAD_REJECT,
236 },
237 {
238 "connect4: attach prog with wrong attach type",
239 connect4_prog_load,
240 BPF_CGROUP_INET4_CONNECT,
241 BPF_CGROUP_INET6_CONNECT,
242 AF_INET,
243 SOCK_STREAM,
244 NULL,
245 0,
246 NULL,
247 0,
248 NULL,
249 ATTACH_REJECT,
250 },
251 {
252 "connect4: rewrite IP & TCP port",
253 connect4_prog_load,
254 BPF_CGROUP_INET4_CONNECT,
255 BPF_CGROUP_INET4_CONNECT,
256 AF_INET,
257 SOCK_STREAM,
258 SERV4_IP,
259 SERV4_PORT,
260 SERV4_REWRITE_IP,
261 SERV4_REWRITE_PORT,
262 SRC4_REWRITE_IP,
263 SUCCESS,
264 },
265 {
266 "connect4: rewrite IP & UDP port",
267 connect4_prog_load,
268 BPF_CGROUP_INET4_CONNECT,
269 BPF_CGROUP_INET4_CONNECT,
270 AF_INET,
271 SOCK_DGRAM,
272 SERV4_IP,
273 SERV4_PORT,
274 SERV4_REWRITE_IP,
275 SERV4_REWRITE_PORT,
276 SRC4_REWRITE_IP,
277 SUCCESS,
278 },
279 {
280 "connect6: load prog with wrong expected attach type",
281 connect6_prog_load,
282 BPF_CGROUP_INET4_CONNECT,
283 BPF_CGROUP_INET6_CONNECT,
284 AF_INET6,
285 SOCK_STREAM,
286 NULL,
287 0,
288 NULL,
289 0,
290 NULL,
291 LOAD_REJECT,
292 },
293 {
294 "connect6: attach prog with wrong attach type",
295 connect6_prog_load,
296 BPF_CGROUP_INET6_CONNECT,
297 BPF_CGROUP_INET4_CONNECT,
298 AF_INET,
299 SOCK_STREAM,
300 NULL,
301 0,
302 NULL,
303 0,
304 NULL,
305 ATTACH_REJECT,
306 },
307 {
308 "connect6: rewrite IP & TCP port",
309 connect6_prog_load,
310 BPF_CGROUP_INET6_CONNECT,
311 BPF_CGROUP_INET6_CONNECT,
312 AF_INET6,
313 SOCK_STREAM,
314 SERV6_IP,
315 SERV6_PORT,
316 SERV6_REWRITE_IP,
317 SERV6_REWRITE_PORT,
318 SRC6_REWRITE_IP,
319 SUCCESS,
320 },
321 {
322 "connect6: rewrite IP & UDP port",
323 connect6_prog_load,
324 BPF_CGROUP_INET6_CONNECT,
325 BPF_CGROUP_INET6_CONNECT,
326 AF_INET6,
327 SOCK_DGRAM,
328 SERV6_IP,
329 SERV6_PORT,
330 SERV6_REWRITE_IP,
331 SERV6_REWRITE_PORT,
332 SRC6_REWRITE_IP,
333 SUCCESS,
334 },
335
336 /* sendmsg */
337 {
338 "sendmsg4: load prog with wrong expected attach type",
339 sendmsg4_rw_asm_prog_load,
340 BPF_CGROUP_UDP6_SENDMSG,
341 BPF_CGROUP_UDP4_SENDMSG,
342 AF_INET,
343 SOCK_DGRAM,
344 NULL,
345 0,
346 NULL,
347 0,
348 NULL,
349 LOAD_REJECT,
350 },
351 {
352 "sendmsg4: attach prog with wrong attach type",
353 sendmsg4_rw_asm_prog_load,
354 BPF_CGROUP_UDP4_SENDMSG,
355 BPF_CGROUP_UDP6_SENDMSG,
356 AF_INET,
357 SOCK_DGRAM,
358 NULL,
359 0,
360 NULL,
361 0,
362 NULL,
363 ATTACH_REJECT,
364 },
365 {
366 "sendmsg4: rewrite IP & port (asm)",
367 sendmsg4_rw_asm_prog_load,
368 BPF_CGROUP_UDP4_SENDMSG,
369 BPF_CGROUP_UDP4_SENDMSG,
370 AF_INET,
371 SOCK_DGRAM,
372 SERV4_IP,
373 SERV4_PORT,
374 SERV4_REWRITE_IP,
375 SERV4_REWRITE_PORT,
376 SRC4_REWRITE_IP,
377 SUCCESS,
378 },
379 {
380 "sendmsg4: rewrite IP & port (C)",
381 sendmsg4_rw_c_prog_load,
382 BPF_CGROUP_UDP4_SENDMSG,
383 BPF_CGROUP_UDP4_SENDMSG,
384 AF_INET,
385 SOCK_DGRAM,
386 SERV4_IP,
387 SERV4_PORT,
388 SERV4_REWRITE_IP,
389 SERV4_REWRITE_PORT,
390 SRC4_REWRITE_IP,
391 SUCCESS,
392 },
393 {
394 "sendmsg4: deny call",
395 sendmsg_deny_prog_load,
396 BPF_CGROUP_UDP4_SENDMSG,
397 BPF_CGROUP_UDP4_SENDMSG,
398 AF_INET,
399 SOCK_DGRAM,
400 SERV4_IP,
401 SERV4_PORT,
402 SERV4_REWRITE_IP,
403 SERV4_REWRITE_PORT,
404 SRC4_REWRITE_IP,
405 SYSCALL_EPERM,
406 },
407 {
408 "sendmsg6: load prog with wrong expected attach type",
409 sendmsg6_rw_asm_prog_load,
410 BPF_CGROUP_UDP4_SENDMSG,
411 BPF_CGROUP_UDP6_SENDMSG,
412 AF_INET6,
413 SOCK_DGRAM,
414 NULL,
415 0,
416 NULL,
417 0,
418 NULL,
419 LOAD_REJECT,
420 },
421 {
422 "sendmsg6: attach prog with wrong attach type",
423 sendmsg6_rw_asm_prog_load,
424 BPF_CGROUP_UDP6_SENDMSG,
425 BPF_CGROUP_UDP4_SENDMSG,
426 AF_INET6,
427 SOCK_DGRAM,
428 NULL,
429 0,
430 NULL,
431 0,
432 NULL,
433 ATTACH_REJECT,
434 },
435 {
436 "sendmsg6: rewrite IP & port (asm)",
437 sendmsg6_rw_asm_prog_load,
438 BPF_CGROUP_UDP6_SENDMSG,
439 BPF_CGROUP_UDP6_SENDMSG,
440 AF_INET6,
441 SOCK_DGRAM,
442 SERV6_IP,
443 SERV6_PORT,
444 SERV6_REWRITE_IP,
445 SERV6_REWRITE_PORT,
446 SRC6_REWRITE_IP,
447 SUCCESS,
448 },
449 {
450 "sendmsg6: rewrite IP & port (C)",
451 sendmsg6_rw_c_prog_load,
452 BPF_CGROUP_UDP6_SENDMSG,
453 BPF_CGROUP_UDP6_SENDMSG,
454 AF_INET6,
455 SOCK_DGRAM,
456 SERV6_IP,
457 SERV6_PORT,
458 SERV6_REWRITE_IP,
459 SERV6_REWRITE_PORT,
460 SRC6_REWRITE_IP,
461 SUCCESS,
462 },
463 {
464 "sendmsg6: IPv4-mapped IPv6",
465 sendmsg6_rw_v4mapped_prog_load,
466 BPF_CGROUP_UDP6_SENDMSG,
467 BPF_CGROUP_UDP6_SENDMSG,
468 AF_INET6,
469 SOCK_DGRAM,
470 SERV6_IP,
471 SERV6_PORT,
472 SERV6_REWRITE_IP,
473 SERV6_REWRITE_PORT,
474 SRC6_REWRITE_IP,
475 SYSCALL_ENOTSUPP,
476 },
477 {
478 "sendmsg6: set dst IP = [::] (BSD'ism)",
479 sendmsg6_rw_wildcard_prog_load,
480 BPF_CGROUP_UDP6_SENDMSG,
481 BPF_CGROUP_UDP6_SENDMSG,
482 AF_INET6,
483 SOCK_DGRAM,
484 SERV6_IP,
485 SERV6_PORT,
486 SERV6_REWRITE_IP,
487 SERV6_REWRITE_PORT,
488 SRC6_REWRITE_IP,
489 SUCCESS,
490 },
491 {
492 "sendmsg6: preserve dst IP = [::] (BSD'ism)",
493 sendmsg_allow_prog_load,
494 BPF_CGROUP_UDP6_SENDMSG,
495 BPF_CGROUP_UDP6_SENDMSG,
496 AF_INET6,
497 SOCK_DGRAM,
498 WILDCARD6_IP,
499 SERV6_PORT,
500 SERV6_REWRITE_IP,
501 SERV6_PORT,
502 SRC6_IP,
503 SUCCESS,
504 },
505 {
506 "sendmsg6: deny call",
507 sendmsg_deny_prog_load,
508 BPF_CGROUP_UDP6_SENDMSG,
509 BPF_CGROUP_UDP6_SENDMSG,
510 AF_INET6,
511 SOCK_DGRAM,
512 SERV6_IP,
513 SERV6_PORT,
514 SERV6_REWRITE_IP,
515 SERV6_REWRITE_PORT,
516 SRC6_REWRITE_IP,
517 SYSCALL_EPERM,
518 },
519
520 /* recvmsg */
521 {
522 "recvmsg4: return code ok",
523 recvmsg_allow_prog_load,
524 BPF_CGROUP_UDP4_RECVMSG,
525 BPF_CGROUP_UDP4_RECVMSG,
526 AF_INET,
527 SOCK_DGRAM,
528 NULL,
529 0,
530 NULL,
531 0,
532 NULL,
533 ATTACH_OKAY,
534 },
535 {
536 "recvmsg4: return code !ok",
537 recvmsg_deny_prog_load,
538 BPF_CGROUP_UDP4_RECVMSG,
539 BPF_CGROUP_UDP4_RECVMSG,
540 AF_INET,
541 SOCK_DGRAM,
542 NULL,
543 0,
544 NULL,
545 0,
546 NULL,
547 LOAD_REJECT,
548 },
549 {
550 "recvmsg6: return code ok",
551 recvmsg_allow_prog_load,
552 BPF_CGROUP_UDP6_RECVMSG,
553 BPF_CGROUP_UDP6_RECVMSG,
554 AF_INET6,
555 SOCK_DGRAM,
556 NULL,
557 0,
558 NULL,
559 0,
560 NULL,
561 ATTACH_OKAY,
562 },
563 {
564 "recvmsg6: return code !ok",
565 recvmsg_deny_prog_load,
566 BPF_CGROUP_UDP6_RECVMSG,
567 BPF_CGROUP_UDP6_RECVMSG,
568 AF_INET6,
569 SOCK_DGRAM,
570 NULL,
571 0,
572 NULL,
573 0,
574 NULL,
575 LOAD_REJECT,
576 },
577 {
578 "recvmsg4: rewrite IP & port (C)",
579 recvmsg4_rw_c_prog_load,
580 BPF_CGROUP_UDP4_RECVMSG,
581 BPF_CGROUP_UDP4_RECVMSG,
582 AF_INET,
583 SOCK_DGRAM,
584 SERV4_REWRITE_IP,
585 SERV4_REWRITE_PORT,
586 SERV4_REWRITE_IP,
587 SERV4_REWRITE_PORT,
588 SERV4_IP,
589 SUCCESS,
590 },
591 {
592 "recvmsg6: rewrite IP & port (C)",
593 recvmsg6_rw_c_prog_load,
594 BPF_CGROUP_UDP6_RECVMSG,
595 BPF_CGROUP_UDP6_RECVMSG,
596 AF_INET6,
597 SOCK_DGRAM,
598 SERV6_REWRITE_IP,
599 SERV6_REWRITE_PORT,
600 SERV6_REWRITE_IP,
601 SERV6_REWRITE_PORT,
602 SERV6_IP,
603 SUCCESS,
604 },
605};
606
607static int mk_sockaddr(int domain, const char *ip, unsigned short port,
608 struct sockaddr *addr, socklen_t addr_len)
609{
610 struct sockaddr_in6 *addr6;
611 struct sockaddr_in *addr4;
612
613 if (domain != AF_INET && domain != AF_INET6) {
614 log_err("Unsupported address family");
615 return -1;
616 }
617
618 memset(addr, 0, addr_len);
619
620 if (domain == AF_INET) {
621 if (addr_len < sizeof(struct sockaddr_in))
622 return -1;
623 addr4 = (struct sockaddr_in *)addr;
624 addr4->sin_family = domain;
625 addr4->sin_port = htons(port);
626 if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
627 log_err("Invalid IPv4: %s", ip);
628 return -1;
629 }
630 } else if (domain == AF_INET6) {
631 if (addr_len < sizeof(struct sockaddr_in6))
632 return -1;
633 addr6 = (struct sockaddr_in6 *)addr;
634 addr6->sin6_family = domain;
635 addr6->sin6_port = htons(port);
636 if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
637 log_err("Invalid IPv6: %s", ip);
638 return -1;
639 }
640 }
641
642 return 0;
643}
644
645static int load_insns(const struct sock_addr_test *test,
646 const struct bpf_insn *insns, size_t insns_cnt)
647{
648 LIBBPF_OPTS(bpf_prog_load_opts, opts);
649 int ret;
650
651 opts.expected_attach_type = test->expected_attach_type;
652 opts.log_buf = bpf_log_buf;
653 opts.log_size = BPF_LOG_BUF_SIZE;
654
655 ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, NULL, "GPL", insns, insns_cnt, &opts);
656 if (ret < 0 && test->expected_result != LOAD_REJECT) {
657 log_err(">>> Loading program error.\n"
658 ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
659 }
660
661 return ret;
662}
663
664static int load_path(const struct sock_addr_test *test, const char *path)
665{
666 struct bpf_object *obj;
667 struct bpf_program *prog;
668 int err;
669
670 obj = bpf_object__open_file(path, NULL);
671 err = libbpf_get_error(obj);
672 if (err) {
673 log_err(">>> Opening BPF object (%s) error.\n", path);
674 return -1;
675 }
676
677 prog = bpf_object__next_program(obj, NULL);
678 if (!prog)
679 goto err_out;
680
681 bpf_program__set_type(prog, BPF_PROG_TYPE_CGROUP_SOCK_ADDR);
682 bpf_program__set_expected_attach_type(prog, test->expected_attach_type);
683 bpf_program__set_flags(prog, testing_prog_flags());
684
685 err = bpf_object__load(obj);
686 if (err) {
687 if (test->expected_result != LOAD_REJECT)
688 log_err(">>> Loading program (%s) error.\n", path);
689 goto err_out;
690 }
691
692 return bpf_program__fd(prog);
693err_out:
694 bpf_object__close(obj);
695 return -1;
696}
697
698static int bind4_prog_load(const struct sock_addr_test *test)
699{
700 return load_path(test, BIND4_PROG_PATH);
701}
702
703static int bind6_prog_load(const struct sock_addr_test *test)
704{
705 return load_path(test, BIND6_PROG_PATH);
706}
707
708static int connect4_prog_load(const struct sock_addr_test *test)
709{
710 return load_path(test, CONNECT4_PROG_PATH);
711}
712
713static int connect6_prog_load(const struct sock_addr_test *test)
714{
715 return load_path(test, CONNECT6_PROG_PATH);
716}
717
718static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
719 int32_t rc)
720{
721 struct bpf_insn insns[] = {
722 /* return rc */
723 BPF_MOV64_IMM(BPF_REG_0, rc),
724 BPF_EXIT_INSN(),
725 };
726 return load_insns(test, insns, ARRAY_SIZE(insns));
727}
728
729static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
730{
731 return xmsg_ret_only_prog_load(test, /*rc*/ 1);
732}
733
734static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
735{
736 return xmsg_ret_only_prog_load(test, /*rc*/ 0);
737}
738
739static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
740{
741 return xmsg_ret_only_prog_load(test, /*rc*/ 1);
742}
743
744static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
745{
746 return xmsg_ret_only_prog_load(test, /*rc*/ 0);
747}
748
749static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
750{
751 struct sockaddr_in dst4_rw_addr;
752 struct in_addr src4_rw_ip;
753
754 if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
755 log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
756 return -1;
757 }
758
759 if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
760 (struct sockaddr *)&dst4_rw_addr,
761 sizeof(dst4_rw_addr)) == -1)
762 return -1;
763
764 struct bpf_insn insns[] = {
765 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
766
767 /* if (sk.family == AF_INET && */
768 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
769 offsetof(struct bpf_sock_addr, family)),
770 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8),
771
772 /* sk.type == SOCK_DGRAM) { */
773 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
774 offsetof(struct bpf_sock_addr, type)),
775 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6),
776
777 /* msg_src_ip4 = src4_rw_ip */
778 BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr),
779 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
780 offsetof(struct bpf_sock_addr, msg_src_ip4)),
781
782 /* user_ip4 = dst4_rw_addr.sin_addr */
783 BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr),
784 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
785 offsetof(struct bpf_sock_addr, user_ip4)),
786
787 /* user_port = dst4_rw_addr.sin_port */
788 BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port),
789 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
790 offsetof(struct bpf_sock_addr, user_port)),
791 /* } */
792
793 /* return 1 */
794 BPF_MOV64_IMM(BPF_REG_0, 1),
795 BPF_EXIT_INSN(),
796 };
797
798 return load_insns(test, insns, ARRAY_SIZE(insns));
799}
800
801static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test)
802{
803 return load_path(test, RECVMSG4_PROG_PATH);
804}
805
806static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
807{
808 return load_path(test, SENDMSG4_PROG_PATH);
809}
810
811static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
812 const char *rw_dst_ip)
813{
814 struct sockaddr_in6 dst6_rw_addr;
815 struct in6_addr src6_rw_ip;
816
817 if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
818 log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
819 return -1;
820 }
821
822 if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
823 (struct sockaddr *)&dst6_rw_addr,
824 sizeof(dst6_rw_addr)) == -1)
825 return -1;
826
827 struct bpf_insn insns[] = {
828 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
829
830 /* if (sk.family == AF_INET6) { */
831 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
832 offsetof(struct bpf_sock_addr, family)),
833 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
834
835#define STORE_IPV6_WORD_N(DST, SRC, N) \
836 BPF_MOV32_IMM(BPF_REG_7, SRC[N]), \
837 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \
838 offsetof(struct bpf_sock_addr, DST[N]))
839
840#define STORE_IPV6(DST, SRC) \
841 STORE_IPV6_WORD_N(DST, SRC, 0), \
842 STORE_IPV6_WORD_N(DST, SRC, 1), \
843 STORE_IPV6_WORD_N(DST, SRC, 2), \
844 STORE_IPV6_WORD_N(DST, SRC, 3)
845
846 STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32),
847 STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32),
848
849 /* user_port = dst6_rw_addr.sin6_port */
850 BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port),
851 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
852 offsetof(struct bpf_sock_addr, user_port)),
853
854 /* } */
855
856 /* return 1 */
857 BPF_MOV64_IMM(BPF_REG_0, 1),
858 BPF_EXIT_INSN(),
859 };
860
861 return load_insns(test, insns, ARRAY_SIZE(insns));
862}
863
864static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
865{
866 return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
867}
868
869static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test)
870{
871 return load_path(test, RECVMSG6_PROG_PATH);
872}
873
874static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
875{
876 return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
877}
878
879static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
880{
881 return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
882}
883
884static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
885{
886 return load_path(test, SENDMSG6_PROG_PATH);
887}
888
889static int cmp_addr(const struct sockaddr_storage *addr1,
890 const struct sockaddr_storage *addr2, int cmp_port)
891{
892 const struct sockaddr_in *four1, *four2;
893 const struct sockaddr_in6 *six1, *six2;
894
895 if (addr1->ss_family != addr2->ss_family)
896 return -1;
897
898 if (addr1->ss_family == AF_INET) {
899 four1 = (const struct sockaddr_in *)addr1;
900 four2 = (const struct sockaddr_in *)addr2;
901 return !((four1->sin_port == four2->sin_port || !cmp_port) &&
902 four1->sin_addr.s_addr == four2->sin_addr.s_addr);
903 } else if (addr1->ss_family == AF_INET6) {
904 six1 = (const struct sockaddr_in6 *)addr1;
905 six2 = (const struct sockaddr_in6 *)addr2;
906 return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
907 !memcmp(p: &six1->sin6_addr, q: &six2->sin6_addr,
908 size: sizeof(struct in6_addr)));
909 }
910
911 return -1;
912}
913
914static int cmp_sock_addr(info_fn fn, int sock1,
915 const struct sockaddr_storage *addr2, int cmp_port)
916{
917 struct sockaddr_storage addr1;
918 socklen_t len1 = sizeof(addr1);
919
920 memset(&addr1, 0, len1);
921 if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
922 return -1;
923
924 return cmp_addr(addr1: &addr1, addr2, cmp_port);
925}
926
927static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
928{
929 return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
930}
931
932static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
933{
934 return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
935}
936
937static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
938{
939 return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
940}
941
942static int start_server(int type, const struct sockaddr_storage *addr,
943 socklen_t addr_len)
944{
945 int fd;
946
947 fd = socket(addr->ss_family, type, 0);
948 if (fd == -1) {
949 log_err("Failed to create server socket");
950 goto out;
951 }
952
953 if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
954 log_err("Failed to bind server socket");
955 goto close_out;
956 }
957
958 if (type == SOCK_STREAM) {
959 if (listen(fd, 128) == -1) {
960 log_err("Failed to listen on server socket");
961 goto close_out;
962 }
963 }
964
965 goto out;
966close_out:
967 close(fd);
968 fd = -1;
969out:
970 return fd;
971}
972
973static int connect_to_server(int type, const struct sockaddr_storage *addr,
974 socklen_t addr_len)
975{
976 int domain;
977 int fd = -1;
978
979 domain = addr->ss_family;
980
981 if (domain != AF_INET && domain != AF_INET6) {
982 log_err("Unsupported address family");
983 goto err;
984 }
985
986 fd = socket(domain, type, 0);
987 if (fd == -1) {
988 log_err("Failed to create client socket");
989 goto err;
990 }
991
992 if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
993 log_err("Fail to connect to server");
994 goto err;
995 }
996
997 goto out;
998err:
999 close(fd);
1000 fd = -1;
1001out:
1002 return fd;
1003}
1004
1005int init_pktinfo(int domain, struct cmsghdr *cmsg)
1006{
1007 struct in6_pktinfo *pktinfo6;
1008 struct in_pktinfo *pktinfo4;
1009
1010 if (domain == AF_INET) {
1011 cmsg->cmsg_level = SOL_IP;
1012 cmsg->cmsg_type = IP_PKTINFO;
1013 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1014 pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg);
1015 memset(pktinfo4, 0, sizeof(struct in_pktinfo));
1016 if (inet_pton(domain, SRC4_IP,
1017 (void *)&pktinfo4->ipi_spec_dst) != 1)
1018 return -1;
1019 } else if (domain == AF_INET6) {
1020 cmsg->cmsg_level = SOL_IPV6;
1021 cmsg->cmsg_type = IPV6_PKTINFO;
1022 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1023 pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1024 memset(pktinfo6, 0, sizeof(struct in6_pktinfo));
1025 if (inet_pton(domain, SRC6_IP,
1026 (void *)&pktinfo6->ipi6_addr) != 1)
1027 return -1;
1028 } else {
1029 return -1;
1030 }
1031
1032 return 0;
1033}
1034
1035static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
1036 socklen_t addr_len, int set_cmsg, int flags,
1037 int *syscall_err)
1038{
1039 union {
1040 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1041 struct cmsghdr align;
1042 } control6;
1043 union {
1044 char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
1045 struct cmsghdr align;
1046 } control4;
1047 struct msghdr hdr;
1048 struct iovec iov;
1049 char data = 'a';
1050 int domain;
1051 int fd = -1;
1052
1053 domain = addr->ss_family;
1054
1055 if (domain != AF_INET && domain != AF_INET6) {
1056 log_err("Unsupported address family");
1057 goto err;
1058 }
1059
1060 fd = socket(domain, type, 0);
1061 if (fd == -1) {
1062 log_err("Failed to create client socket");
1063 goto err;
1064 }
1065
1066 memset(&iov, 0, sizeof(iov));
1067 iov.iov_base = &data;
1068 iov.iov_len = sizeof(data);
1069
1070 memset(&hdr, 0, sizeof(hdr));
1071 hdr.msg_name = (void *)addr;
1072 hdr.msg_namelen = addr_len;
1073 hdr.msg_iov = &iov;
1074 hdr.msg_iovlen = 1;
1075
1076 if (set_cmsg) {
1077 if (domain == AF_INET) {
1078 hdr.msg_control = &control4;
1079 hdr.msg_controllen = sizeof(control4.buf);
1080 } else if (domain == AF_INET6) {
1081 hdr.msg_control = &control6;
1082 hdr.msg_controllen = sizeof(control6.buf);
1083 }
1084 if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
1085 log_err("Fail to init pktinfo");
1086 goto err;
1087 }
1088 }
1089
1090 if (sendmsg(fd, &hdr, flags) != sizeof(data)) {
1091 log_err("Fail to send message to server");
1092 *syscall_err = errno;
1093 goto err;
1094 }
1095
1096 goto out;
1097err:
1098 close(fd);
1099 fd = -1;
1100out:
1101 return fd;
1102}
1103
1104static int fastconnect_to_server(const struct sockaddr_storage *addr,
1105 socklen_t addr_len)
1106{
1107 int sendmsg_err;
1108
1109 return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0,
1110 MSG_FASTOPEN, &sendmsg_err);
1111}
1112
1113static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
1114{
1115 struct timeval tv;
1116 struct msghdr hdr;
1117 struct iovec iov;
1118 char data[64];
1119 fd_set rfds;
1120
1121 FD_ZERO(&rfds);
1122 FD_SET(sockfd, &rfds);
1123
1124 tv.tv_sec = 2;
1125 tv.tv_usec = 0;
1126
1127 if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 ||
1128 !FD_ISSET(sockfd, &rfds))
1129 return -1;
1130
1131 memset(&iov, 0, sizeof(iov));
1132 iov.iov_base = data;
1133 iov.iov_len = sizeof(data);
1134
1135 memset(&hdr, 0, sizeof(hdr));
1136 hdr.msg_name = src_addr;
1137 hdr.msg_namelen = sizeof(struct sockaddr_storage);
1138 hdr.msg_iov = &iov;
1139 hdr.msg_iovlen = 1;
1140
1141 return recvmsg(sockfd, &hdr, 0);
1142}
1143
1144static int init_addrs(const struct sock_addr_test *test,
1145 struct sockaddr_storage *requested_addr,
1146 struct sockaddr_storage *expected_addr,
1147 struct sockaddr_storage *expected_src_addr)
1148{
1149 socklen_t addr_len = sizeof(struct sockaddr_storage);
1150
1151 if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
1152 (struct sockaddr *)expected_addr, addr_len) == -1)
1153 goto err;
1154
1155 if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
1156 (struct sockaddr *)requested_addr, addr_len) == -1)
1157 goto err;
1158
1159 if (test->expected_src_ip &&
1160 mk_sockaddr(test->domain, test->expected_src_ip, 0,
1161 (struct sockaddr *)expected_src_addr, addr_len) == -1)
1162 goto err;
1163
1164 return 0;
1165err:
1166 return -1;
1167}
1168
1169static int run_bind_test_case(const struct sock_addr_test *test)
1170{
1171 socklen_t addr_len = sizeof(struct sockaddr_storage);
1172 struct sockaddr_storage requested_addr;
1173 struct sockaddr_storage expected_addr;
1174 int clientfd = -1;
1175 int servfd = -1;
1176 int err = 0;
1177
1178 if (init_addrs(test, requested_addr: &requested_addr, expected_addr: &expected_addr, NULL))
1179 goto err;
1180
1181 servfd = start_server(test->type, &requested_addr, addr_len);
1182 if (servfd == -1)
1183 goto err;
1184
1185 if (cmp_local_addr(sock1: servfd, addr2: &expected_addr))
1186 goto err;
1187
1188 /* Try to connect to server just in case */
1189 clientfd = connect_to_server(test->type, &expected_addr, addr_len);
1190 if (clientfd == -1)
1191 goto err;
1192
1193 goto out;
1194err:
1195 err = -1;
1196out:
1197 close(clientfd);
1198 close(servfd);
1199 return err;
1200}
1201
1202static int run_connect_test_case(const struct sock_addr_test *test)
1203{
1204 socklen_t addr_len = sizeof(struct sockaddr_storage);
1205 struct sockaddr_storage expected_src_addr;
1206 struct sockaddr_storage requested_addr;
1207 struct sockaddr_storage expected_addr;
1208 int clientfd = -1;
1209 int servfd = -1;
1210 int err = 0;
1211
1212 if (init_addrs(test, requested_addr: &requested_addr, expected_addr: &expected_addr,
1213 expected_src_addr: &expected_src_addr))
1214 goto err;
1215
1216 /* Prepare server to connect to */
1217 servfd = start_server(test->type, &expected_addr, addr_len);
1218 if (servfd == -1)
1219 goto err;
1220
1221 clientfd = connect_to_server(test->type, &requested_addr, addr_len);
1222 if (clientfd == -1)
1223 goto err;
1224
1225 /* Make sure src and dst addrs were overridden properly */
1226 if (cmp_peer_addr(sock1: clientfd, addr2: &expected_addr))
1227 goto err;
1228
1229 if (cmp_local_ip(sock1: clientfd, addr2: &expected_src_addr))
1230 goto err;
1231
1232 if (test->type == SOCK_STREAM) {
1233 /* Test TCP Fast Open scenario */
1234 clientfd = fastconnect_to_server(&requested_addr, addr_len);
1235 if (clientfd == -1)
1236 goto err;
1237
1238 /* Make sure src and dst addrs were overridden properly */
1239 if (cmp_peer_addr(sock1: clientfd, addr2: &expected_addr))
1240 goto err;
1241
1242 if (cmp_local_ip(sock1: clientfd, addr2: &expected_src_addr))
1243 goto err;
1244 }
1245
1246 goto out;
1247err:
1248 err = -1;
1249out:
1250 close(clientfd);
1251 close(servfd);
1252 return err;
1253}
1254
1255static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
1256{
1257 socklen_t addr_len = sizeof(struct sockaddr_storage);
1258 struct sockaddr_storage expected_addr;
1259 struct sockaddr_storage server_addr;
1260 struct sockaddr_storage sendmsg_addr;
1261 struct sockaddr_storage recvmsg_addr;
1262 int clientfd = -1;
1263 int servfd = -1;
1264 int set_cmsg;
1265 int err = 0;
1266
1267 if (test->type != SOCK_DGRAM)
1268 goto err;
1269
1270 if (init_addrs(test, requested_addr: &sendmsg_addr, expected_addr: &server_addr, expected_src_addr: &expected_addr))
1271 goto err;
1272
1273 /* Prepare server to sendmsg to */
1274 servfd = start_server(test->type, &server_addr, addr_len);
1275 if (servfd == -1)
1276 goto err;
1277
1278 for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
1279 if (clientfd >= 0)
1280 close(clientfd);
1281
1282 clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
1283 addr_len, set_cmsg, /*flags*/0,
1284 &err);
1285 if (err)
1286 goto out;
1287 else if (clientfd == -1)
1288 goto err;
1289
1290 /* Try to receive message on server instead of using
1291 * getpeername(2) on client socket, to check that client's
1292 * destination address was rewritten properly, since
1293 * getpeername(2) doesn't work with unconnected datagram
1294 * sockets.
1295 *
1296 * Get source address from recvmsg(2) as well to make sure
1297 * source was rewritten properly: getsockname(2) can't be used
1298 * since socket is unconnected and source defined for one
1299 * specific packet may differ from the one used by default and
1300 * returned by getsockname(2).
1301 */
1302 if (recvmsg_from_client(sockfd: servfd, src_addr: &recvmsg_addr) == -1)
1303 goto err;
1304
1305 if (cmp_addr(addr1: &recvmsg_addr, addr2: &expected_addr, /*cmp_port*/0))
1306 goto err;
1307 }
1308
1309 goto out;
1310err:
1311 err = -1;
1312out:
1313 close(clientfd);
1314 close(servfd);
1315 return err;
1316}
1317
1318static int run_test_case(int cgfd, const struct sock_addr_test *test)
1319{
1320 int progfd = -1;
1321 int err = 0;
1322
1323 printf("Test case: %s .. ", test->descr);
1324
1325 progfd = test->loadfn(test);
1326 if (test->expected_result == LOAD_REJECT && progfd < 0)
1327 goto out;
1328 else if (test->expected_result == LOAD_REJECT || progfd < 0)
1329 goto err;
1330
1331 err = bpf_prog_attach(progfd, cgfd, test->attach_type,
1332 BPF_F_ALLOW_OVERRIDE);
1333 if (test->expected_result == ATTACH_REJECT && err) {
1334 err = 0; /* error was expected, reset it */
1335 goto out;
1336 } else if (test->expected_result == ATTACH_REJECT || err) {
1337 goto err;
1338 } else if (test->expected_result == ATTACH_OKAY) {
1339 err = 0;
1340 goto out;
1341 }
1342
1343 switch (test->attach_type) {
1344 case BPF_CGROUP_INET4_BIND:
1345 case BPF_CGROUP_INET6_BIND:
1346 err = run_bind_test_case(test);
1347 break;
1348 case BPF_CGROUP_INET4_CONNECT:
1349 case BPF_CGROUP_INET6_CONNECT:
1350 err = run_connect_test_case(test);
1351 break;
1352 case BPF_CGROUP_UDP4_SENDMSG:
1353 case BPF_CGROUP_UDP6_SENDMSG:
1354 err = run_xmsg_test_case(test, max_cmsg: 1);
1355 break;
1356 case BPF_CGROUP_UDP4_RECVMSG:
1357 case BPF_CGROUP_UDP6_RECVMSG:
1358 err = run_xmsg_test_case(test, max_cmsg: 0);
1359 break;
1360 default:
1361 goto err;
1362 }
1363
1364 if (test->expected_result == SYSCALL_EPERM && err == EPERM) {
1365 err = 0; /* error was expected, reset it */
1366 goto out;
1367 }
1368
1369 if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) {
1370 err = 0; /* error was expected, reset it */
1371 goto out;
1372 }
1373
1374 if (err || test->expected_result != SUCCESS)
1375 goto err;
1376
1377 goto out;
1378err:
1379 err = -1;
1380out:
1381 /* Detaching w/o checking return code: best effort attempt. */
1382 if (progfd != -1)
1383 bpf_prog_detach(cgfd, test->attach_type);
1384 close(progfd);
1385 printf("[%s]\n", err ? "FAIL" : "PASS");
1386 return err;
1387}
1388
1389static int run_tests(int cgfd)
1390{
1391 int passes = 0;
1392 int fails = 0;
1393 int i;
1394
1395 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1396 if (run_test_case(cgfd, test: &tests[i]))
1397 ++fails;
1398 else
1399 ++passes;
1400 }
1401 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1402 return fails ? -1 : 0;
1403}
1404
1405int main(int argc, char **argv)
1406{
1407 int cgfd = -1;
1408 int err = 0;
1409
1410 if (argc < 2) {
1411 fprintf(stderr,
1412 "%s has to be run via %s.sh. Skip direct run.\n",
1413 argv[0], argv[0]);
1414 exit(err);
1415 }
1416
1417 cgfd = cgroup_setup_and_join(CG_PATH);
1418 if (cgfd < 0)
1419 goto err;
1420
1421 /* Use libbpf 1.0 API mode */
1422 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1423
1424 if (run_tests(cgfd))
1425 goto err;
1426
1427 goto out;
1428err:
1429 err = -1;
1430out:
1431 close(cgfd);
1432 cleanup_cgroup_environment();
1433 return err;
1434}
1435

source code of linux/tools/testing/selftests/bpf/test_sock_addr.c