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