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, port; 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 port.u4_addr32 = htons(SERV4_PORT); 689 690 if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, 691 (struct sockaddr *)&addr4_rw, sizeof(addr4_rw)) == -1) 692 return -1; 693 694 /* See [1]. */ 695 struct bpf_insn insns[] = { 696 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 697 698 /* if (sk.family == AF_INET && */ 699 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 700 offsetof(struct bpf_sock_addr, family)), 701 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 32), 702 703 /* (sk.type == SOCK_DGRAM || sk.type == SOCK_STREAM) && */ 704 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 705 offsetof(struct bpf_sock_addr, type)), 706 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 1), 707 BPF_JMP_A(1), 708 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_STREAM, 28), 709 710 /* 1st_byte_of_user_ip4 == expected && */ 711 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 712 offsetof(struct bpf_sock_addr, user_ip4)), 713 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[0], 26), 714 715 /* 2nd_byte_of_user_ip4 == expected && */ 716 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 717 offsetof(struct bpf_sock_addr, user_ip4) + 1), 718 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[1], 24), 719 720 /* 3rd_byte_of_user_ip4 == expected && */ 721 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 722 offsetof(struct bpf_sock_addr, user_ip4) + 2), 723 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[2], 22), 724 725 /* 4th_byte_of_user_ip4 == expected && */ 726 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 727 offsetof(struct bpf_sock_addr, user_ip4) + 3), 728 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[3], 20), 729 730 /* 1st_half_of_user_ip4 == expected && */ 731 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 732 offsetof(struct bpf_sock_addr, user_ip4)), 733 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr16[0], 18), 734 735 /* 2nd_half_of_user_ip4 == expected && */ 736 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 737 offsetof(struct bpf_sock_addr, user_ip4) + 2), 738 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr16[1], 16), 739 740 /* whole_user_ip4 == expected && */ 741 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 742 offsetof(struct bpf_sock_addr, user_ip4)), 743 BPF_LD_IMM64(BPF_REG_8, ip4.u4_addr32), /* See [2]. */ 744 BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 12), 745 746 /* 1st_byte_of_user_port == expected && */ 747 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 748 offsetof(struct bpf_sock_addr, user_port)), 749 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, port.u4_addr8[0], 10), 750 751 /* 1st_half_of_user_port == expected && */ 752 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 753 offsetof(struct bpf_sock_addr, user_port)), 754 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, port.u4_addr16[0], 8), 755 756 /* user_port == expected) { */ 757 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 758 offsetof(struct bpf_sock_addr, user_port)), 759 BPF_LD_IMM64(BPF_REG_8, port.u4_addr32), /* See [2]. */ 760 BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 4), 761 762 /* user_ip4 = addr4_rw.sin_addr */ 763 BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_addr.s_addr), 764 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 765 offsetof(struct bpf_sock_addr, user_ip4)), 766 767 /* user_port = addr4_rw.sin_port */ 768 BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_port), 769 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 770 offsetof(struct bpf_sock_addr, user_port)), 771 /* } */ 772 773 /* return 1 */ 774 BPF_MOV64_IMM(BPF_REG_0, 1), 775 BPF_EXIT_INSN(), 776 }; 777 778 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 779 } 780 781 static int bind6_prog_load(const struct sock_addr_test *test) 782 { 783 struct sockaddr_in6 addr6_rw; 784 struct in6_addr ip6; 785 786 if (inet_pton(AF_INET6, SERV6_IP, (void *)&ip6) != 1) { 787 log_err("Invalid IPv6: %s", SERV6_IP); 788 return -1; 789 } 790 791 if (mk_sockaddr(AF_INET6, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, 792 (struct sockaddr *)&addr6_rw, sizeof(addr6_rw)) == -1) 793 return -1; 794 795 /* See [1]. */ 796 struct bpf_insn insns[] = { 797 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 798 799 /* if (sk.family == AF_INET6 && */ 800 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 801 offsetof(struct bpf_sock_addr, family)), 802 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18), 803 804 /* 5th_byte_of_user_ip6 == expected && */ 805 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 806 offsetof(struct bpf_sock_addr, user_ip6[1])), 807 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr[4], 16), 808 809 /* 3rd_half_of_user_ip6 == expected && */ 810 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 811 offsetof(struct bpf_sock_addr, user_ip6[1])), 812 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr16[2], 14), 813 814 /* last_word_of_user_ip6 == expected) { */ 815 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 816 offsetof(struct bpf_sock_addr, user_ip6[3])), 817 BPF_LD_IMM64(BPF_REG_8, ip6.s6_addr32[3]), /* See [2]. */ 818 BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 10), 819 820 821 #define STORE_IPV6_WORD(N) \ 822 BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_addr.s6_addr32[N]), \ 823 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \ 824 offsetof(struct bpf_sock_addr, user_ip6[N])) 825 826 /* user_ip6 = addr6_rw.sin6_addr */ 827 STORE_IPV6_WORD(0), 828 STORE_IPV6_WORD(1), 829 STORE_IPV6_WORD(2), 830 STORE_IPV6_WORD(3), 831 832 /* user_port = addr6_rw.sin6_port */ 833 BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_port), 834 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 835 offsetof(struct bpf_sock_addr, user_port)), 836 837 /* } */ 838 839 /* return 1 */ 840 BPF_MOV64_IMM(BPF_REG_0, 1), 841 BPF_EXIT_INSN(), 842 }; 843 844 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 845 } 846 847 static int load_path(const struct sock_addr_test *test, const char *path) 848 { 849 struct bpf_prog_load_attr attr; 850 struct bpf_object *obj; 851 int prog_fd; 852 853 memset(&attr, 0, sizeof(struct bpf_prog_load_attr)); 854 attr.file = path; 855 attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; 856 attr.expected_attach_type = test->expected_attach_type; 857 attr.prog_flags = BPF_F_TEST_RND_HI32; 858 859 if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) { 860 if (test->expected_result != LOAD_REJECT) 861 log_err(">>> Loading program (%s) error.\n", path); 862 return -1; 863 } 864 865 return prog_fd; 866 } 867 868 static int connect4_prog_load(const struct sock_addr_test *test) 869 { 870 return load_path(test, CONNECT4_PROG_PATH); 871 } 872 873 static int connect6_prog_load(const struct sock_addr_test *test) 874 { 875 return load_path(test, CONNECT6_PROG_PATH); 876 } 877 878 static int xmsg_ret_only_prog_load(const struct sock_addr_test *test, 879 int32_t rc) 880 { 881 struct bpf_insn insns[] = { 882 /* return rc */ 883 BPF_MOV64_IMM(BPF_REG_0, rc), 884 BPF_EXIT_INSN(), 885 }; 886 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 887 } 888 889 static int sendmsg_allow_prog_load(const struct sock_addr_test *test) 890 { 891 return xmsg_ret_only_prog_load(test, /*rc*/ 1); 892 } 893 894 static int sendmsg_deny_prog_load(const struct sock_addr_test *test) 895 { 896 return xmsg_ret_only_prog_load(test, /*rc*/ 0); 897 } 898 899 static int recvmsg_allow_prog_load(const struct sock_addr_test *test) 900 { 901 return xmsg_ret_only_prog_load(test, /*rc*/ 1); 902 } 903 904 static int recvmsg_deny_prog_load(const struct sock_addr_test *test) 905 { 906 return xmsg_ret_only_prog_load(test, /*rc*/ 0); 907 } 908 909 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) 910 { 911 struct sockaddr_in dst4_rw_addr; 912 struct in_addr src4_rw_ip; 913 914 if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) { 915 log_err("Invalid IPv4: %s", SRC4_REWRITE_IP); 916 return -1; 917 } 918 919 if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, 920 (struct sockaddr *)&dst4_rw_addr, 921 sizeof(dst4_rw_addr)) == -1) 922 return -1; 923 924 struct bpf_insn insns[] = { 925 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 926 927 /* if (sk.family == AF_INET && */ 928 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 929 offsetof(struct bpf_sock_addr, family)), 930 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8), 931 932 /* sk.type == SOCK_DGRAM) { */ 933 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 934 offsetof(struct bpf_sock_addr, type)), 935 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6), 936 937 /* msg_src_ip4 = src4_rw_ip */ 938 BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr), 939 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 940 offsetof(struct bpf_sock_addr, msg_src_ip4)), 941 942 /* user_ip4 = dst4_rw_addr.sin_addr */ 943 BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr), 944 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 945 offsetof(struct bpf_sock_addr, user_ip4)), 946 947 /* user_port = dst4_rw_addr.sin_port */ 948 BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port), 949 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 950 offsetof(struct bpf_sock_addr, user_port)), 951 /* } */ 952 953 /* return 1 */ 954 BPF_MOV64_IMM(BPF_REG_0, 1), 955 BPF_EXIT_INSN(), 956 }; 957 958 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 959 } 960 961 static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test) 962 { 963 struct sockaddr_in src4_rw_addr; 964 965 if (mk_sockaddr(AF_INET, SERV4_IP, SERV4_PORT, 966 (struct sockaddr *)&src4_rw_addr, 967 sizeof(src4_rw_addr)) == -1) 968 return -1; 969 970 struct bpf_insn insns[] = { 971 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 972 973 /* if (sk.family == AF_INET && */ 974 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 975 offsetof(struct bpf_sock_addr, family)), 976 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 6), 977 978 /* sk.type == SOCK_DGRAM) { */ 979 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 980 offsetof(struct bpf_sock_addr, type)), 981 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 4), 982 983 /* user_ip4 = src4_rw_addr.sin_addr */ 984 BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_addr.s_addr), 985 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 986 offsetof(struct bpf_sock_addr, user_ip4)), 987 988 /* user_port = src4_rw_addr.sin_port */ 989 BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_port), 990 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 991 offsetof(struct bpf_sock_addr, user_port)), 992 /* } */ 993 994 /* return 1 */ 995 BPF_MOV64_IMM(BPF_REG_0, 1), 996 BPF_EXIT_INSN(), 997 }; 998 999 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 1000 } 1001 1002 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test) 1003 { 1004 return load_path(test, SENDMSG4_PROG_PATH); 1005 } 1006 1007 static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test, 1008 const char *rw_dst_ip) 1009 { 1010 struct sockaddr_in6 dst6_rw_addr; 1011 struct in6_addr src6_rw_ip; 1012 1013 if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) { 1014 log_err("Invalid IPv6: %s", SRC6_REWRITE_IP); 1015 return -1; 1016 } 1017 1018 if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT, 1019 (struct sockaddr *)&dst6_rw_addr, 1020 sizeof(dst6_rw_addr)) == -1) 1021 return -1; 1022 1023 struct bpf_insn insns[] = { 1024 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 1025 1026 /* if (sk.family == AF_INET6) { */ 1027 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 1028 offsetof(struct bpf_sock_addr, family)), 1029 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18), 1030 1031 #define STORE_IPV6_WORD_N(DST, SRC, N) \ 1032 BPF_MOV32_IMM(BPF_REG_7, SRC[N]), \ 1033 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \ 1034 offsetof(struct bpf_sock_addr, DST[N])) 1035 1036 #define STORE_IPV6(DST, SRC) \ 1037 STORE_IPV6_WORD_N(DST, SRC, 0), \ 1038 STORE_IPV6_WORD_N(DST, SRC, 1), \ 1039 STORE_IPV6_WORD_N(DST, SRC, 2), \ 1040 STORE_IPV6_WORD_N(DST, SRC, 3) 1041 1042 STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32), 1043 STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32), 1044 1045 /* user_port = dst6_rw_addr.sin6_port */ 1046 BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port), 1047 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 1048 offsetof(struct bpf_sock_addr, user_port)), 1049 1050 /* } */ 1051 1052 /* return 1 */ 1053 BPF_MOV64_IMM(BPF_REG_0, 1), 1054 BPF_EXIT_INSN(), 1055 }; 1056 1057 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 1058 } 1059 1060 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test) 1061 { 1062 return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP); 1063 } 1064 1065 static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test) 1066 { 1067 struct sockaddr_in6 src6_rw_addr; 1068 1069 if (mk_sockaddr(AF_INET6, SERV6_IP, SERV6_PORT, 1070 (struct sockaddr *)&src6_rw_addr, 1071 sizeof(src6_rw_addr)) == -1) 1072 return -1; 1073 1074 struct bpf_insn insns[] = { 1075 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 1076 1077 /* if (sk.family == AF_INET6) { */ 1078 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 1079 offsetof(struct bpf_sock_addr, family)), 1080 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 10), 1081 1082 STORE_IPV6(user_ip6, src6_rw_addr.sin6_addr.s6_addr32), 1083 1084 /* user_port = dst6_rw_addr.sin6_port */ 1085 BPF_MOV32_IMM(BPF_REG_7, src6_rw_addr.sin6_port), 1086 BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 1087 offsetof(struct bpf_sock_addr, user_port)), 1088 /* } */ 1089 1090 /* return 1 */ 1091 BPF_MOV64_IMM(BPF_REG_0, 1), 1092 BPF_EXIT_INSN(), 1093 }; 1094 1095 return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 1096 } 1097 1098 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test) 1099 { 1100 return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP); 1101 } 1102 1103 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test) 1104 { 1105 return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP); 1106 } 1107 1108 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test) 1109 { 1110 return load_path(test, SENDMSG6_PROG_PATH); 1111 } 1112 1113 static int cmp_addr(const struct sockaddr_storage *addr1, 1114 const struct sockaddr_storage *addr2, int cmp_port) 1115 { 1116 const struct sockaddr_in *four1, *four2; 1117 const struct sockaddr_in6 *six1, *six2; 1118 1119 if (addr1->ss_family != addr2->ss_family) 1120 return -1; 1121 1122 if (addr1->ss_family == AF_INET) { 1123 four1 = (const struct sockaddr_in *)addr1; 1124 four2 = (const struct sockaddr_in *)addr2; 1125 return !((four1->sin_port == four2->sin_port || !cmp_port) && 1126 four1->sin_addr.s_addr == four2->sin_addr.s_addr); 1127 } else if (addr1->ss_family == AF_INET6) { 1128 six1 = (const struct sockaddr_in6 *)addr1; 1129 six2 = (const struct sockaddr_in6 *)addr2; 1130 return !((six1->sin6_port == six2->sin6_port || !cmp_port) && 1131 !memcmp(&six1->sin6_addr, &six2->sin6_addr, 1132 sizeof(struct in6_addr))); 1133 } 1134 1135 return -1; 1136 } 1137 1138 static int cmp_sock_addr(info_fn fn, int sock1, 1139 const struct sockaddr_storage *addr2, int cmp_port) 1140 { 1141 struct sockaddr_storage addr1; 1142 socklen_t len1 = sizeof(addr1); 1143 1144 memset(&addr1, 0, len1); 1145 if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0) 1146 return -1; 1147 1148 return cmp_addr(&addr1, addr2, cmp_port); 1149 } 1150 1151 static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2) 1152 { 1153 return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0); 1154 } 1155 1156 static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2) 1157 { 1158 return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1); 1159 } 1160 1161 static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2) 1162 { 1163 return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1); 1164 } 1165 1166 static int start_server(int type, const struct sockaddr_storage *addr, 1167 socklen_t addr_len) 1168 { 1169 int fd; 1170 1171 fd = socket(addr->ss_family, type, 0); 1172 if (fd == -1) { 1173 log_err("Failed to create server socket"); 1174 goto out; 1175 } 1176 1177 if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) { 1178 log_err("Failed to bind server socket"); 1179 goto close_out; 1180 } 1181 1182 if (type == SOCK_STREAM) { 1183 if (listen(fd, 128) == -1) { 1184 log_err("Failed to listen on server socket"); 1185 goto close_out; 1186 } 1187 } 1188 1189 goto out; 1190 close_out: 1191 close(fd); 1192 fd = -1; 1193 out: 1194 return fd; 1195 } 1196 1197 static int connect_to_server(int type, const struct sockaddr_storage *addr, 1198 socklen_t addr_len) 1199 { 1200 int domain; 1201 int fd = -1; 1202 1203 domain = addr->ss_family; 1204 1205 if (domain != AF_INET && domain != AF_INET6) { 1206 log_err("Unsupported address family"); 1207 goto err; 1208 } 1209 1210 fd = socket(domain, type, 0); 1211 if (fd == -1) { 1212 log_err("Failed to create client socket"); 1213 goto err; 1214 } 1215 1216 if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) { 1217 log_err("Fail to connect to server"); 1218 goto err; 1219 } 1220 1221 goto out; 1222 err: 1223 close(fd); 1224 fd = -1; 1225 out: 1226 return fd; 1227 } 1228 1229 int init_pktinfo(int domain, struct cmsghdr *cmsg) 1230 { 1231 struct in6_pktinfo *pktinfo6; 1232 struct in_pktinfo *pktinfo4; 1233 1234 if (domain == AF_INET) { 1235 cmsg->cmsg_level = SOL_IP; 1236 cmsg->cmsg_type = IP_PKTINFO; 1237 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 1238 pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg); 1239 memset(pktinfo4, 0, sizeof(struct in_pktinfo)); 1240 if (inet_pton(domain, SRC4_IP, 1241 (void *)&pktinfo4->ipi_spec_dst) != 1) 1242 return -1; 1243 } else if (domain == AF_INET6) { 1244 cmsg->cmsg_level = SOL_IPV6; 1245 cmsg->cmsg_type = IPV6_PKTINFO; 1246 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1247 pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); 1248 memset(pktinfo6, 0, sizeof(struct in6_pktinfo)); 1249 if (inet_pton(domain, SRC6_IP, 1250 (void *)&pktinfo6->ipi6_addr) != 1) 1251 return -1; 1252 } else { 1253 return -1; 1254 } 1255 1256 return 0; 1257 } 1258 1259 static int sendmsg_to_server(int type, const struct sockaddr_storage *addr, 1260 socklen_t addr_len, int set_cmsg, int flags, 1261 int *syscall_err) 1262 { 1263 union { 1264 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 1265 struct cmsghdr align; 1266 } control6; 1267 union { 1268 char buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 1269 struct cmsghdr align; 1270 } control4; 1271 struct msghdr hdr; 1272 struct iovec iov; 1273 char data = 'a'; 1274 int domain; 1275 int fd = -1; 1276 1277 domain = addr->ss_family; 1278 1279 if (domain != AF_INET && domain != AF_INET6) { 1280 log_err("Unsupported address family"); 1281 goto err; 1282 } 1283 1284 fd = socket(domain, type, 0); 1285 if (fd == -1) { 1286 log_err("Failed to create client socket"); 1287 goto err; 1288 } 1289 1290 memset(&iov, 0, sizeof(iov)); 1291 iov.iov_base = &data; 1292 iov.iov_len = sizeof(data); 1293 1294 memset(&hdr, 0, sizeof(hdr)); 1295 hdr.msg_name = (void *)addr; 1296 hdr.msg_namelen = addr_len; 1297 hdr.msg_iov = &iov; 1298 hdr.msg_iovlen = 1; 1299 1300 if (set_cmsg) { 1301 if (domain == AF_INET) { 1302 hdr.msg_control = &control4; 1303 hdr.msg_controllen = sizeof(control4.buf); 1304 } else if (domain == AF_INET6) { 1305 hdr.msg_control = &control6; 1306 hdr.msg_controllen = sizeof(control6.buf); 1307 } 1308 if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) { 1309 log_err("Fail to init pktinfo"); 1310 goto err; 1311 } 1312 } 1313 1314 if (sendmsg(fd, &hdr, flags) != sizeof(data)) { 1315 log_err("Fail to send message to server"); 1316 *syscall_err = errno; 1317 goto err; 1318 } 1319 1320 goto out; 1321 err: 1322 close(fd); 1323 fd = -1; 1324 out: 1325 return fd; 1326 } 1327 1328 static int fastconnect_to_server(const struct sockaddr_storage *addr, 1329 socklen_t addr_len) 1330 { 1331 int sendmsg_err; 1332 1333 return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0, 1334 MSG_FASTOPEN, &sendmsg_err); 1335 } 1336 1337 static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr) 1338 { 1339 struct timeval tv; 1340 struct msghdr hdr; 1341 struct iovec iov; 1342 char data[64]; 1343 fd_set rfds; 1344 1345 FD_ZERO(&rfds); 1346 FD_SET(sockfd, &rfds); 1347 1348 tv.tv_sec = 2; 1349 tv.tv_usec = 0; 1350 1351 if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 || 1352 !FD_ISSET(sockfd, &rfds)) 1353 return -1; 1354 1355 memset(&iov, 0, sizeof(iov)); 1356 iov.iov_base = data; 1357 iov.iov_len = sizeof(data); 1358 1359 memset(&hdr, 0, sizeof(hdr)); 1360 hdr.msg_name = src_addr; 1361 hdr.msg_namelen = sizeof(struct sockaddr_storage); 1362 hdr.msg_iov = &iov; 1363 hdr.msg_iovlen = 1; 1364 1365 return recvmsg(sockfd, &hdr, 0); 1366 } 1367 1368 static int init_addrs(const struct sock_addr_test *test, 1369 struct sockaddr_storage *requested_addr, 1370 struct sockaddr_storage *expected_addr, 1371 struct sockaddr_storage *expected_src_addr) 1372 { 1373 socklen_t addr_len = sizeof(struct sockaddr_storage); 1374 1375 if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port, 1376 (struct sockaddr *)expected_addr, addr_len) == -1) 1377 goto err; 1378 1379 if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port, 1380 (struct sockaddr *)requested_addr, addr_len) == -1) 1381 goto err; 1382 1383 if (test->expected_src_ip && 1384 mk_sockaddr(test->domain, test->expected_src_ip, 0, 1385 (struct sockaddr *)expected_src_addr, addr_len) == -1) 1386 goto err; 1387 1388 return 0; 1389 err: 1390 return -1; 1391 } 1392 1393 static int run_bind_test_case(const struct sock_addr_test *test) 1394 { 1395 socklen_t addr_len = sizeof(struct sockaddr_storage); 1396 struct sockaddr_storage requested_addr; 1397 struct sockaddr_storage expected_addr; 1398 int clientfd = -1; 1399 int servfd = -1; 1400 int err = 0; 1401 1402 if (init_addrs(test, &requested_addr, &expected_addr, NULL)) 1403 goto err; 1404 1405 servfd = start_server(test->type, &requested_addr, addr_len); 1406 if (servfd == -1) 1407 goto err; 1408 1409 if (cmp_local_addr(servfd, &expected_addr)) 1410 goto err; 1411 1412 /* Try to connect to server just in case */ 1413 clientfd = connect_to_server(test->type, &expected_addr, addr_len); 1414 if (clientfd == -1) 1415 goto err; 1416 1417 goto out; 1418 err: 1419 err = -1; 1420 out: 1421 close(clientfd); 1422 close(servfd); 1423 return err; 1424 } 1425 1426 static int run_connect_test_case(const struct sock_addr_test *test) 1427 { 1428 socklen_t addr_len = sizeof(struct sockaddr_storage); 1429 struct sockaddr_storage expected_src_addr; 1430 struct sockaddr_storage requested_addr; 1431 struct sockaddr_storage expected_addr; 1432 int clientfd = -1; 1433 int servfd = -1; 1434 int err = 0; 1435 1436 if (init_addrs(test, &requested_addr, &expected_addr, 1437 &expected_src_addr)) 1438 goto err; 1439 1440 /* Prepare server to connect to */ 1441 servfd = start_server(test->type, &expected_addr, addr_len); 1442 if (servfd == -1) 1443 goto err; 1444 1445 clientfd = connect_to_server(test->type, &requested_addr, addr_len); 1446 if (clientfd == -1) 1447 goto err; 1448 1449 /* Make sure src and dst addrs were overridden properly */ 1450 if (cmp_peer_addr(clientfd, &expected_addr)) 1451 goto err; 1452 1453 if (cmp_local_ip(clientfd, &expected_src_addr)) 1454 goto err; 1455 1456 if (test->type == SOCK_STREAM) { 1457 /* Test TCP Fast Open scenario */ 1458 clientfd = fastconnect_to_server(&requested_addr, addr_len); 1459 if (clientfd == -1) 1460 goto err; 1461 1462 /* Make sure src and dst addrs were overridden properly */ 1463 if (cmp_peer_addr(clientfd, &expected_addr)) 1464 goto err; 1465 1466 if (cmp_local_ip(clientfd, &expected_src_addr)) 1467 goto err; 1468 } 1469 1470 goto out; 1471 err: 1472 err = -1; 1473 out: 1474 close(clientfd); 1475 close(servfd); 1476 return err; 1477 } 1478 1479 static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg) 1480 { 1481 socklen_t addr_len = sizeof(struct sockaddr_storage); 1482 struct sockaddr_storage expected_addr; 1483 struct sockaddr_storage server_addr; 1484 struct sockaddr_storage sendmsg_addr; 1485 struct sockaddr_storage recvmsg_addr; 1486 int clientfd = -1; 1487 int servfd = -1; 1488 int set_cmsg; 1489 int err = 0; 1490 1491 if (test->type != SOCK_DGRAM) 1492 goto err; 1493 1494 if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr)) 1495 goto err; 1496 1497 /* Prepare server to sendmsg to */ 1498 servfd = start_server(test->type, &server_addr, addr_len); 1499 if (servfd == -1) 1500 goto err; 1501 1502 for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) { 1503 if (clientfd >= 0) 1504 close(clientfd); 1505 1506 clientfd = sendmsg_to_server(test->type, &sendmsg_addr, 1507 addr_len, set_cmsg, /*flags*/0, 1508 &err); 1509 if (err) 1510 goto out; 1511 else if (clientfd == -1) 1512 goto err; 1513 1514 /* Try to receive message on server instead of using 1515 * getpeername(2) on client socket, to check that client's 1516 * destination address was rewritten properly, since 1517 * getpeername(2) doesn't work with unconnected datagram 1518 * sockets. 1519 * 1520 * Get source address from recvmsg(2) as well to make sure 1521 * source was rewritten properly: getsockname(2) can't be used 1522 * since socket is unconnected and source defined for one 1523 * specific packet may differ from the one used by default and 1524 * returned by getsockname(2). 1525 */ 1526 if (recvmsg_from_client(servfd, &recvmsg_addr) == -1) 1527 goto err; 1528 1529 if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0)) 1530 goto err; 1531 } 1532 1533 goto out; 1534 err: 1535 err = -1; 1536 out: 1537 close(clientfd); 1538 close(servfd); 1539 return err; 1540 } 1541 1542 static int run_test_case(int cgfd, const struct sock_addr_test *test) 1543 { 1544 int progfd = -1; 1545 int err = 0; 1546 1547 printf("Test case: %s .. ", test->descr); 1548 1549 progfd = test->loadfn(test); 1550 if (test->expected_result == LOAD_REJECT && progfd < 0) 1551 goto out; 1552 else if (test->expected_result == LOAD_REJECT || progfd < 0) 1553 goto err; 1554 1555 err = bpf_prog_attach(progfd, cgfd, test->attach_type, 1556 BPF_F_ALLOW_OVERRIDE); 1557 if (test->expected_result == ATTACH_REJECT && err) { 1558 err = 0; /* error was expected, reset it */ 1559 goto out; 1560 } else if (test->expected_result == ATTACH_REJECT || err) { 1561 goto err; 1562 } else if (test->expected_result == ATTACH_OKAY) { 1563 err = 0; 1564 goto out; 1565 } 1566 1567 switch (test->attach_type) { 1568 case BPF_CGROUP_INET4_BIND: 1569 case BPF_CGROUP_INET6_BIND: 1570 err = run_bind_test_case(test); 1571 break; 1572 case BPF_CGROUP_INET4_CONNECT: 1573 case BPF_CGROUP_INET6_CONNECT: 1574 err = run_connect_test_case(test); 1575 break; 1576 case BPF_CGROUP_UDP4_SENDMSG: 1577 case BPF_CGROUP_UDP6_SENDMSG: 1578 err = run_xmsg_test_case(test, 1); 1579 break; 1580 case BPF_CGROUP_UDP4_RECVMSG: 1581 case BPF_CGROUP_UDP6_RECVMSG: 1582 err = run_xmsg_test_case(test, 0); 1583 break; 1584 default: 1585 goto err; 1586 } 1587 1588 if (test->expected_result == SYSCALL_EPERM && err == EPERM) { 1589 err = 0; /* error was expected, reset it */ 1590 goto out; 1591 } 1592 1593 if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) { 1594 err = 0; /* error was expected, reset it */ 1595 goto out; 1596 } 1597 1598 if (err || test->expected_result != SUCCESS) 1599 goto err; 1600 1601 goto out; 1602 err: 1603 err = -1; 1604 out: 1605 /* Detaching w/o checking return code: best effort attempt. */ 1606 if (progfd != -1) 1607 bpf_prog_detach(cgfd, test->attach_type); 1608 close(progfd); 1609 printf("[%s]\n", err ? "FAIL" : "PASS"); 1610 return err; 1611 } 1612 1613 static int run_tests(int cgfd) 1614 { 1615 int passes = 0; 1616 int fails = 0; 1617 int i; 1618 1619 for (i = 0; i < ARRAY_SIZE(tests); ++i) { 1620 if (run_test_case(cgfd, &tests[i])) 1621 ++fails; 1622 else 1623 ++passes; 1624 } 1625 printf("Summary: %d PASSED, %d FAILED\n", passes, fails); 1626 return fails ? -1 : 0; 1627 } 1628 1629 int main(int argc, char **argv) 1630 { 1631 int cgfd = -1; 1632 int err = 0; 1633 1634 if (argc < 2) { 1635 fprintf(stderr, 1636 "%s has to be run via %s.sh. Skip direct run.\n", 1637 argv[0], argv[0]); 1638 exit(err); 1639 } 1640 1641 if (setup_cgroup_environment()) 1642 goto err; 1643 1644 cgfd = create_and_get_cgroup(CG_PATH); 1645 if (cgfd < 0) 1646 goto err; 1647 1648 if (join_cgroup(CG_PATH)) 1649 goto err; 1650 1651 if (run_tests(cgfd)) 1652 goto err; 1653 1654 goto out; 1655 err: 1656 err = -1; 1657 out: 1658 close(cgfd); 1659 cleanup_cgroup_environment(); 1660 return err; 1661 } 1662