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