Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v6.18-rc5 2003 lines 50 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Landlock tests - Network 4 * 5 * Copyright © 2022-2023 Huawei Tech. Co., Ltd. 6 * Copyright © 2023 Microsoft Corporation 7 */ 8 9#define _GNU_SOURCE 10#include <arpa/inet.h> 11#include <errno.h> 12#include <fcntl.h> 13#include <linux/landlock.h> 14#include <linux/in.h> 15#include <sched.h> 16#include <stdint.h> 17#include <string.h> 18#include <sys/prctl.h> 19#include <sys/socket.h> 20#include <sys/syscall.h> 21#include <sys/un.h> 22 23#include "audit.h" 24#include "common.h" 25 26const short sock_port_start = (1 << 10); 27 28static const char loopback_ipv4[] = "127.0.0.1"; 29static const char loopback_ipv6[] = "::1"; 30 31/* Number pending connections queue to be hold. */ 32const short backlog = 10; 33 34enum sandbox_type { 35 NO_SANDBOX, 36 /* This may be used to test rules that allow *and* deny accesses. */ 37 TCP_SANDBOX, 38}; 39 40static int set_service(struct service_fixture *const srv, 41 const struct protocol_variant prot, 42 const unsigned short index) 43{ 44 memset(srv, 0, sizeof(*srv)); 45 46 /* 47 * Copies all protocol properties in case of the variant only contains 48 * a subset of them. 49 */ 50 srv->protocol = prot; 51 52 /* Checks for port overflow. */ 53 if (index > 2) 54 return 1; 55 srv->port = sock_port_start << (2 * index); 56 57 switch (prot.domain) { 58 case AF_UNSPEC: 59 case AF_INET: 60 srv->ipv4_addr.sin_family = prot.domain; 61 srv->ipv4_addr.sin_port = htons(srv->port); 62 srv->ipv4_addr.sin_addr.s_addr = inet_addr(loopback_ipv4); 63 return 0; 64 65 case AF_INET6: 66 srv->ipv6_addr.sin6_family = prot.domain; 67 srv->ipv6_addr.sin6_port = htons(srv->port); 68 inet_pton(AF_INET6, loopback_ipv6, &srv->ipv6_addr.sin6_addr); 69 return 0; 70 71 case AF_UNIX: 72 set_unix_address(srv, index); 73 return 0; 74 } 75 return 1; 76} 77 78static void setup_loopback(struct __test_metadata *const _metadata) 79{ 80 set_cap(_metadata, CAP_SYS_ADMIN); 81 ASSERT_EQ(0, unshare(CLONE_NEWNET)); 82 clear_cap(_metadata, CAP_SYS_ADMIN); 83 84 set_ambient_cap(_metadata, CAP_NET_ADMIN); 85 ASSERT_EQ(0, system("ip link set dev lo up")); 86 clear_ambient_cap(_metadata, CAP_NET_ADMIN); 87} 88 89static bool prot_is_tcp(const struct protocol_variant *const prot) 90{ 91 return (prot->domain == AF_INET || prot->domain == AF_INET6) && 92 prot->type == SOCK_STREAM && 93 (prot->protocol == IPPROTO_TCP || prot->protocol == IPPROTO_IP); 94} 95 96static bool is_restricted(const struct protocol_variant *const prot, 97 const enum sandbox_type sandbox) 98{ 99 if (sandbox == TCP_SANDBOX) 100 return prot_is_tcp(prot); 101 return false; 102} 103 104static int socket_variant(const struct service_fixture *const srv) 105{ 106 int ret; 107 108 ret = socket(srv->protocol.domain, srv->protocol.type | SOCK_CLOEXEC, 109 srv->protocol.protocol); 110 if (ret < 0) 111 return -errno; 112 return ret; 113} 114 115#ifndef SIN6_LEN_RFC2133 116#define SIN6_LEN_RFC2133 24 117#endif 118 119static socklen_t get_addrlen(const struct service_fixture *const srv, 120 const bool minimal) 121{ 122 switch (srv->protocol.domain) { 123 case AF_UNSPEC: 124 case AF_INET: 125 return sizeof(srv->ipv4_addr); 126 127 case AF_INET6: 128 if (minimal) 129 return SIN6_LEN_RFC2133; 130 return sizeof(srv->ipv6_addr); 131 132 case AF_UNIX: 133 if (minimal) 134 return sizeof(srv->unix_addr) - 135 sizeof(srv->unix_addr.sun_path); 136 return srv->unix_addr_len; 137 138 default: 139 return 0; 140 } 141} 142 143static void set_port(struct service_fixture *const srv, uint16_t port) 144{ 145 switch (srv->protocol.domain) { 146 case AF_UNSPEC: 147 case AF_INET: 148 srv->ipv4_addr.sin_port = htons(port); 149 return; 150 151 case AF_INET6: 152 srv->ipv6_addr.sin6_port = htons(port); 153 return; 154 155 default: 156 return; 157 } 158} 159 160static uint16_t get_binded_port(int socket_fd, 161 const struct protocol_variant *const prot) 162{ 163 struct sockaddr_in ipv4_addr; 164 struct sockaddr_in6 ipv6_addr; 165 socklen_t ipv4_addr_len, ipv6_addr_len; 166 167 /* Gets binded port. */ 168 switch (prot->domain) { 169 case AF_UNSPEC: 170 case AF_INET: 171 ipv4_addr_len = sizeof(ipv4_addr); 172 getsockname(socket_fd, &ipv4_addr, &ipv4_addr_len); 173 return ntohs(ipv4_addr.sin_port); 174 175 case AF_INET6: 176 ipv6_addr_len = sizeof(ipv6_addr); 177 getsockname(socket_fd, &ipv6_addr, &ipv6_addr_len); 178 return ntohs(ipv6_addr.sin6_port); 179 180 default: 181 return 0; 182 } 183} 184 185static int bind_variant_addrlen(const int sock_fd, 186 const struct service_fixture *const srv, 187 const socklen_t addrlen) 188{ 189 int ret; 190 191 switch (srv->protocol.domain) { 192 case AF_UNSPEC: 193 case AF_INET: 194 ret = bind(sock_fd, &srv->ipv4_addr, addrlen); 195 break; 196 197 case AF_INET6: 198 ret = bind(sock_fd, &srv->ipv6_addr, addrlen); 199 break; 200 201 case AF_UNIX: 202 ret = bind(sock_fd, &srv->unix_addr, addrlen); 203 break; 204 205 default: 206 errno = EAFNOSUPPORT; 207 return -errno; 208 } 209 210 if (ret < 0) 211 return -errno; 212 return ret; 213} 214 215static int bind_variant(const int sock_fd, 216 const struct service_fixture *const srv) 217{ 218 return bind_variant_addrlen(sock_fd, srv, get_addrlen(srv, false)); 219} 220 221static int connect_variant_addrlen(const int sock_fd, 222 const struct service_fixture *const srv, 223 const socklen_t addrlen) 224{ 225 int ret; 226 227 switch (srv->protocol.domain) { 228 case AF_UNSPEC: 229 case AF_INET: 230 ret = connect(sock_fd, &srv->ipv4_addr, addrlen); 231 break; 232 233 case AF_INET6: 234 ret = connect(sock_fd, &srv->ipv6_addr, addrlen); 235 break; 236 237 case AF_UNIX: 238 ret = connect(sock_fd, &srv->unix_addr, addrlen); 239 break; 240 241 default: 242 errno = -EAFNOSUPPORT; 243 return -errno; 244 } 245 246 if (ret < 0) 247 return -errno; 248 return ret; 249} 250 251static int connect_variant(const int sock_fd, 252 const struct service_fixture *const srv) 253{ 254 return connect_variant_addrlen(sock_fd, srv, get_addrlen(srv, false)); 255} 256 257FIXTURE(protocol) 258{ 259 struct service_fixture srv0, srv1, srv2, unspec_any0, unspec_srv0; 260}; 261 262FIXTURE_VARIANT(protocol) 263{ 264 const enum sandbox_type sandbox; 265 const struct protocol_variant prot; 266}; 267 268FIXTURE_SETUP(protocol) 269{ 270 const struct protocol_variant prot_unspec = { 271 .domain = AF_UNSPEC, 272 .type = SOCK_STREAM, 273 }; 274 275 disable_caps(_metadata); 276 277 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); 278 ASSERT_EQ(0, set_service(&self->srv1, variant->prot, 1)); 279 ASSERT_EQ(0, set_service(&self->srv2, variant->prot, 2)); 280 281 ASSERT_EQ(0, set_service(&self->unspec_srv0, prot_unspec, 0)); 282 283 ASSERT_EQ(0, set_service(&self->unspec_any0, prot_unspec, 0)); 284 self->unspec_any0.ipv4_addr.sin_addr.s_addr = htonl(INADDR_ANY); 285 286 setup_loopback(_metadata); 287}; 288 289FIXTURE_TEARDOWN(protocol) 290{ 291} 292 293/* clang-format off */ 294FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_tcp1) { 295 /* clang-format on */ 296 .sandbox = NO_SANDBOX, 297 .prot = { 298 .domain = AF_INET, 299 .type = SOCK_STREAM, 300 /* IPPROTO_IP == 0 */ 301 .protocol = IPPROTO_IP, 302 }, 303}; 304 305/* clang-format off */ 306FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_tcp2) { 307 /* clang-format on */ 308 .sandbox = NO_SANDBOX, 309 .prot = { 310 .domain = AF_INET, 311 .type = SOCK_STREAM, 312 .protocol = IPPROTO_TCP, 313 }, 314}; 315 316/* clang-format off */ 317FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_mptcp) { 318 /* clang-format on */ 319 .sandbox = NO_SANDBOX, 320 .prot = { 321 .domain = AF_INET, 322 .type = SOCK_STREAM, 323 .protocol = IPPROTO_MPTCP, 324 }, 325}; 326 327/* clang-format off */ 328FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_tcp1) { 329 /* clang-format on */ 330 .sandbox = NO_SANDBOX, 331 .prot = { 332 .domain = AF_INET6, 333 .type = SOCK_STREAM, 334 /* IPPROTO_IP == 0 */ 335 .protocol = IPPROTO_IP, 336 }, 337}; 338 339/* clang-format off */ 340FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_tcp2) { 341 /* clang-format on */ 342 .sandbox = NO_SANDBOX, 343 .prot = { 344 .domain = AF_INET6, 345 .type = SOCK_STREAM, 346 .protocol = IPPROTO_TCP, 347 }, 348}; 349 350/* clang-format off */ 351FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_mptcp) { 352 /* clang-format on */ 353 .sandbox = NO_SANDBOX, 354 .prot = { 355 .domain = AF_INET6, 356 .type = SOCK_STREAM, 357 .protocol = IPPROTO_MPTCP, 358 }, 359}; 360 361/* clang-format off */ 362FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_udp) { 363 /* clang-format on */ 364 .sandbox = NO_SANDBOX, 365 .prot = { 366 .domain = AF_INET, 367 .type = SOCK_DGRAM, 368 }, 369}; 370 371/* clang-format off */ 372FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_udp) { 373 /* clang-format on */ 374 .sandbox = NO_SANDBOX, 375 .prot = { 376 .domain = AF_INET6, 377 .type = SOCK_DGRAM, 378 }, 379}; 380 381/* clang-format off */ 382FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_stream) { 383 /* clang-format on */ 384 .sandbox = NO_SANDBOX, 385 .prot = { 386 .domain = AF_UNIX, 387 .type = SOCK_STREAM, 388 }, 389}; 390 391/* clang-format off */ 392FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_datagram) { 393 /* clang-format on */ 394 .sandbox = NO_SANDBOX, 395 .prot = { 396 .domain = AF_UNIX, 397 .type = SOCK_DGRAM, 398 }, 399}; 400 401/* clang-format off */ 402FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_tcp1) { 403 /* clang-format on */ 404 .sandbox = TCP_SANDBOX, 405 .prot = { 406 .domain = AF_INET, 407 .type = SOCK_STREAM, 408 /* IPPROTO_IP == 0 */ 409 .protocol = IPPROTO_IP, 410 }, 411}; 412 413/* clang-format off */ 414FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_tcp2) { 415 /* clang-format on */ 416 .sandbox = TCP_SANDBOX, 417 .prot = { 418 .domain = AF_INET, 419 .type = SOCK_STREAM, 420 .protocol = IPPROTO_TCP, 421 }, 422}; 423 424/* clang-format off */ 425FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_mptcp) { 426 /* clang-format on */ 427 .sandbox = TCP_SANDBOX, 428 .prot = { 429 .domain = AF_INET, 430 .type = SOCK_STREAM, 431 .protocol = IPPROTO_MPTCP, 432 }, 433}; 434 435/* clang-format off */ 436FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_tcp1) { 437 /* clang-format on */ 438 .sandbox = TCP_SANDBOX, 439 .prot = { 440 .domain = AF_INET6, 441 .type = SOCK_STREAM, 442 /* IPPROTO_IP == 0 */ 443 .protocol = IPPROTO_IP, 444 }, 445}; 446 447/* clang-format off */ 448FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_tcp2) { 449 /* clang-format on */ 450 .sandbox = TCP_SANDBOX, 451 .prot = { 452 .domain = AF_INET6, 453 .type = SOCK_STREAM, 454 .protocol = IPPROTO_TCP, 455 }, 456}; 457 458/* clang-format off */ 459FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_mptcp) { 460 /* clang-format on */ 461 .sandbox = TCP_SANDBOX, 462 .prot = { 463 .domain = AF_INET6, 464 .type = SOCK_STREAM, 465 .protocol = IPPROTO_MPTCP, 466 }, 467}; 468 469/* clang-format off */ 470FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_udp) { 471 /* clang-format on */ 472 .sandbox = TCP_SANDBOX, 473 .prot = { 474 .domain = AF_INET, 475 .type = SOCK_DGRAM, 476 }, 477}; 478 479/* clang-format off */ 480FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_udp) { 481 /* clang-format on */ 482 .sandbox = TCP_SANDBOX, 483 .prot = { 484 .domain = AF_INET6, 485 .type = SOCK_DGRAM, 486 }, 487}; 488 489/* clang-format off */ 490FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_stream) { 491 /* clang-format on */ 492 .sandbox = TCP_SANDBOX, 493 .prot = { 494 .domain = AF_UNIX, 495 .type = SOCK_STREAM, 496 }, 497}; 498 499/* clang-format off */ 500FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_datagram) { 501 /* clang-format on */ 502 .sandbox = TCP_SANDBOX, 503 .prot = { 504 .domain = AF_UNIX, 505 .type = SOCK_DGRAM, 506 }, 507}; 508 509static void test_bind_and_connect(struct __test_metadata *const _metadata, 510 const struct service_fixture *const srv, 511 const bool deny_bind, const bool deny_connect) 512{ 513 char buf = '\0'; 514 int inval_fd, bind_fd, client_fd, status, ret; 515 pid_t child; 516 517 /* Starts invalid addrlen tests with bind. */ 518 inval_fd = socket_variant(srv); 519 ASSERT_LE(0, inval_fd) 520 { 521 TH_LOG("Failed to create socket: %s", strerror(errno)); 522 } 523 524 /* Tries to bind with zero as addrlen. */ 525 EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv, 0)); 526 527 /* Tries to bind with too small addrlen. */ 528 EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv, 529 get_addrlen(srv, true) - 1)); 530 531 /* Tries to bind with minimal addrlen. */ 532 ret = bind_variant_addrlen(inval_fd, srv, get_addrlen(srv, true)); 533 if (deny_bind) { 534 EXPECT_EQ(-EACCES, ret); 535 } else { 536 EXPECT_EQ(0, ret) 537 { 538 TH_LOG("Failed to bind to socket: %s", strerror(errno)); 539 } 540 } 541 EXPECT_EQ(0, close(inval_fd)); 542 543 /* Starts invalid addrlen tests with connect. */ 544 inval_fd = socket_variant(srv); 545 ASSERT_LE(0, inval_fd); 546 547 /* Tries to connect with zero as addrlen. */ 548 EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv, 0)); 549 550 /* Tries to connect with too small addrlen. */ 551 EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv, 552 get_addrlen(srv, true) - 1)); 553 554 /* Tries to connect with minimal addrlen. */ 555 ret = connect_variant_addrlen(inval_fd, srv, get_addrlen(srv, true)); 556 if (srv->protocol.domain == AF_UNIX) { 557 EXPECT_EQ(-EINVAL, ret); 558 } else if (deny_connect) { 559 EXPECT_EQ(-EACCES, ret); 560 } else if (srv->protocol.type == SOCK_STREAM) { 561 /* No listening server, whatever the value of deny_bind. */ 562 EXPECT_EQ(-ECONNREFUSED, ret); 563 } else { 564 EXPECT_EQ(0, ret) 565 { 566 TH_LOG("Failed to connect to socket: %s", 567 strerror(errno)); 568 } 569 } 570 EXPECT_EQ(0, close(inval_fd)); 571 572 /* Starts connection tests. */ 573 bind_fd = socket_variant(srv); 574 ASSERT_LE(0, bind_fd); 575 576 ret = bind_variant(bind_fd, srv); 577 if (deny_bind) { 578 EXPECT_EQ(-EACCES, ret); 579 } else { 580 EXPECT_EQ(0, ret); 581 582 /* Creates a listening socket. */ 583 if (srv->protocol.type == SOCK_STREAM) 584 EXPECT_EQ(0, listen(bind_fd, backlog)); 585 } 586 587 child = fork(); 588 ASSERT_LE(0, child); 589 if (child == 0) { 590 int connect_fd, ret; 591 592 /* Closes listening socket for the child. */ 593 EXPECT_EQ(0, close(bind_fd)); 594 595 /* Starts connection tests. */ 596 connect_fd = socket_variant(srv); 597 ASSERT_LE(0, connect_fd); 598 ret = connect_variant(connect_fd, srv); 599 if (deny_connect) { 600 EXPECT_EQ(-EACCES, ret); 601 } else if (deny_bind) { 602 /* No listening server. */ 603 EXPECT_EQ(-ECONNREFUSED, ret); 604 } else { 605 EXPECT_EQ(0, ret); 606 EXPECT_EQ(1, write(connect_fd, ".", 1)); 607 } 608 609 EXPECT_EQ(0, close(connect_fd)); 610 _exit(_metadata->exit_code); 611 return; 612 } 613 614 /* Accepts connection from the child. */ 615 client_fd = bind_fd; 616 if (!deny_bind && !deny_connect) { 617 if (srv->protocol.type == SOCK_STREAM) { 618 client_fd = accept(bind_fd, NULL, 0); 619 ASSERT_LE(0, client_fd); 620 } 621 622 EXPECT_EQ(1, read(client_fd, &buf, 1)); 623 EXPECT_EQ('.', buf); 624 } 625 626 EXPECT_EQ(child, waitpid(child, &status, 0)); 627 EXPECT_EQ(1, WIFEXITED(status)); 628 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 629 630 /* Closes connection, if any. */ 631 if (client_fd != bind_fd) 632 EXPECT_LE(0, close(client_fd)); 633 634 /* Closes listening socket. */ 635 EXPECT_EQ(0, close(bind_fd)); 636} 637 638TEST_F(protocol, bind) 639{ 640 if (variant->sandbox == TCP_SANDBOX) { 641 const struct landlock_ruleset_attr ruleset_attr = { 642 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 643 LANDLOCK_ACCESS_NET_CONNECT_TCP, 644 }; 645 const struct landlock_net_port_attr tcp_bind_connect_p0 = { 646 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 647 LANDLOCK_ACCESS_NET_CONNECT_TCP, 648 .port = self->srv0.port, 649 }; 650 const struct landlock_net_port_attr tcp_connect_p1 = { 651 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, 652 .port = self->srv1.port, 653 }; 654 int ruleset_fd; 655 656 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 657 sizeof(ruleset_attr), 0); 658 ASSERT_LE(0, ruleset_fd); 659 660 /* Allows connect and bind for the first port. */ 661 ASSERT_EQ(0, 662 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 663 &tcp_bind_connect_p0, 0)); 664 665 /* Allows connect and denies bind for the second port. */ 666 ASSERT_EQ(0, 667 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 668 &tcp_connect_p1, 0)); 669 670 enforce_ruleset(_metadata, ruleset_fd); 671 EXPECT_EQ(0, close(ruleset_fd)); 672 } 673 674 /* Binds a socket to the first port. */ 675 test_bind_and_connect(_metadata, &self->srv0, false, false); 676 677 /* Binds a socket to the second port. */ 678 test_bind_and_connect(_metadata, &self->srv1, 679 is_restricted(&variant->prot, variant->sandbox), 680 false); 681 682 /* Binds a socket to the third port. */ 683 test_bind_and_connect(_metadata, &self->srv2, 684 is_restricted(&variant->prot, variant->sandbox), 685 is_restricted(&variant->prot, variant->sandbox)); 686} 687 688TEST_F(protocol, connect) 689{ 690 if (variant->sandbox == TCP_SANDBOX) { 691 const struct landlock_ruleset_attr ruleset_attr = { 692 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 693 LANDLOCK_ACCESS_NET_CONNECT_TCP, 694 }; 695 const struct landlock_net_port_attr tcp_bind_connect_p0 = { 696 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 697 LANDLOCK_ACCESS_NET_CONNECT_TCP, 698 .port = self->srv0.port, 699 }; 700 const struct landlock_net_port_attr tcp_bind_p1 = { 701 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 702 .port = self->srv1.port, 703 }; 704 int ruleset_fd; 705 706 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 707 sizeof(ruleset_attr), 0); 708 ASSERT_LE(0, ruleset_fd); 709 710 /* Allows connect and bind for the first port. */ 711 ASSERT_EQ(0, 712 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 713 &tcp_bind_connect_p0, 0)); 714 715 /* Allows bind and denies connect for the second port. */ 716 ASSERT_EQ(0, 717 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 718 &tcp_bind_p1, 0)); 719 720 enforce_ruleset(_metadata, ruleset_fd); 721 EXPECT_EQ(0, close(ruleset_fd)); 722 } 723 724 test_bind_and_connect(_metadata, &self->srv0, false, false); 725 726 test_bind_and_connect(_metadata, &self->srv1, false, 727 is_restricted(&variant->prot, variant->sandbox)); 728 729 test_bind_and_connect(_metadata, &self->srv2, 730 is_restricted(&variant->prot, variant->sandbox), 731 is_restricted(&variant->prot, variant->sandbox)); 732} 733 734TEST_F(protocol, bind_unspec) 735{ 736 const struct landlock_ruleset_attr ruleset_attr = { 737 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, 738 }; 739 const struct landlock_net_port_attr tcp_bind = { 740 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 741 .port = self->srv0.port, 742 }; 743 int bind_fd, ret; 744 745 if (variant->sandbox == TCP_SANDBOX) { 746 const int ruleset_fd = landlock_create_ruleset( 747 &ruleset_attr, sizeof(ruleset_attr), 0); 748 ASSERT_LE(0, ruleset_fd); 749 750 /* Allows bind. */ 751 ASSERT_EQ(0, 752 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 753 &tcp_bind, 0)); 754 enforce_ruleset(_metadata, ruleset_fd); 755 EXPECT_EQ(0, close(ruleset_fd)); 756 } 757 758 bind_fd = socket_variant(&self->srv0); 759 ASSERT_LE(0, bind_fd); 760 761 /* Allowed bind on AF_UNSPEC/INADDR_ANY. */ 762 ret = bind_variant(bind_fd, &self->unspec_any0); 763 if (variant->prot.domain == AF_INET) { 764 EXPECT_EQ(0, ret) 765 { 766 TH_LOG("Failed to bind to unspec/any socket: %s", 767 strerror(errno)); 768 } 769 } else { 770 EXPECT_EQ(-EINVAL, ret); 771 } 772 EXPECT_EQ(0, close(bind_fd)); 773 774 if (variant->sandbox == TCP_SANDBOX) { 775 const int ruleset_fd = landlock_create_ruleset( 776 &ruleset_attr, sizeof(ruleset_attr), 0); 777 ASSERT_LE(0, ruleset_fd); 778 779 /* Denies bind. */ 780 enforce_ruleset(_metadata, ruleset_fd); 781 EXPECT_EQ(0, close(ruleset_fd)); 782 } 783 784 bind_fd = socket_variant(&self->srv0); 785 ASSERT_LE(0, bind_fd); 786 787 /* Denied bind on AF_UNSPEC/INADDR_ANY. */ 788 ret = bind_variant(bind_fd, &self->unspec_any0); 789 if (variant->prot.domain == AF_INET) { 790 if (is_restricted(&variant->prot, variant->sandbox)) { 791 EXPECT_EQ(-EACCES, ret); 792 } else { 793 EXPECT_EQ(0, ret); 794 } 795 } else { 796 EXPECT_EQ(-EINVAL, ret); 797 } 798 EXPECT_EQ(0, close(bind_fd)); 799 800 /* Checks bind with AF_UNSPEC and the loopback address. */ 801 bind_fd = socket_variant(&self->srv0); 802 ASSERT_LE(0, bind_fd); 803 ret = bind_variant(bind_fd, &self->unspec_srv0); 804 if (variant->prot.domain == AF_INET) { 805 EXPECT_EQ(-EAFNOSUPPORT, ret); 806 } else { 807 EXPECT_EQ(-EINVAL, ret) 808 { 809 TH_LOG("Wrong bind error: %s", strerror(errno)); 810 } 811 } 812 EXPECT_EQ(0, close(bind_fd)); 813} 814 815TEST_F(protocol, connect_unspec) 816{ 817 const struct landlock_ruleset_attr ruleset_attr = { 818 .handled_access_net = LANDLOCK_ACCESS_NET_CONNECT_TCP, 819 }; 820 const struct landlock_net_port_attr tcp_connect = { 821 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, 822 .port = self->srv0.port, 823 }; 824 int bind_fd, client_fd, status; 825 pid_t child; 826 827 /* Specific connection tests. */ 828 bind_fd = socket_variant(&self->srv0); 829 ASSERT_LE(0, bind_fd); 830 EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); 831 if (self->srv0.protocol.type == SOCK_STREAM) 832 EXPECT_EQ(0, listen(bind_fd, backlog)); 833 834 child = fork(); 835 ASSERT_LE(0, child); 836 if (child == 0) { 837 int connect_fd, ret; 838 839 /* Closes listening socket for the child. */ 840 EXPECT_EQ(0, close(bind_fd)); 841 842 connect_fd = socket_variant(&self->srv0); 843 ASSERT_LE(0, connect_fd); 844 EXPECT_EQ(0, connect_variant(connect_fd, &self->srv0)); 845 846 /* Tries to connect again, or set peer. */ 847 ret = connect_variant(connect_fd, &self->srv0); 848 if (self->srv0.protocol.type == SOCK_STREAM) { 849 EXPECT_EQ(-EISCONN, ret); 850 } else { 851 EXPECT_EQ(0, ret); 852 } 853 854 if (variant->sandbox == TCP_SANDBOX) { 855 const int ruleset_fd = landlock_create_ruleset( 856 &ruleset_attr, sizeof(ruleset_attr), 0); 857 ASSERT_LE(0, ruleset_fd); 858 859 /* Allows connect. */ 860 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, 861 LANDLOCK_RULE_NET_PORT, 862 &tcp_connect, 0)); 863 enforce_ruleset(_metadata, ruleset_fd); 864 EXPECT_EQ(0, close(ruleset_fd)); 865 } 866 867 /* Disconnects already connected socket, or set peer. */ 868 ret = connect_variant(connect_fd, &self->unspec_any0); 869 if (self->srv0.protocol.domain == AF_UNIX && 870 self->srv0.protocol.type == SOCK_STREAM) { 871 EXPECT_EQ(-EINVAL, ret); 872 } else { 873 EXPECT_EQ(0, ret); 874 } 875 876 /* Tries to reconnect, or set peer. */ 877 ret = connect_variant(connect_fd, &self->srv0); 878 if (self->srv0.protocol.domain == AF_UNIX && 879 self->srv0.protocol.type == SOCK_STREAM) { 880 EXPECT_EQ(-EISCONN, ret); 881 } else { 882 EXPECT_EQ(0, ret); 883 } 884 885 if (variant->sandbox == TCP_SANDBOX) { 886 const int ruleset_fd = landlock_create_ruleset( 887 &ruleset_attr, sizeof(ruleset_attr), 0); 888 ASSERT_LE(0, ruleset_fd); 889 890 /* Denies connect. */ 891 enforce_ruleset(_metadata, ruleset_fd); 892 EXPECT_EQ(0, close(ruleset_fd)); 893 } 894 895 ret = connect_variant(connect_fd, &self->unspec_any0); 896 if (self->srv0.protocol.domain == AF_UNIX && 897 self->srv0.protocol.type == SOCK_STREAM) { 898 EXPECT_EQ(-EINVAL, ret); 899 } else { 900 /* Always allowed to disconnect. */ 901 EXPECT_EQ(0, ret); 902 } 903 904 EXPECT_EQ(0, close(connect_fd)); 905 _exit(_metadata->exit_code); 906 return; 907 } 908 909 client_fd = bind_fd; 910 if (self->srv0.protocol.type == SOCK_STREAM) { 911 client_fd = accept(bind_fd, NULL, 0); 912 ASSERT_LE(0, client_fd); 913 } 914 915 EXPECT_EQ(child, waitpid(child, &status, 0)); 916 EXPECT_EQ(1, WIFEXITED(status)); 917 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 918 919 /* Closes connection, if any. */ 920 if (client_fd != bind_fd) 921 EXPECT_LE(0, close(client_fd)); 922 923 /* Closes listening socket. */ 924 EXPECT_EQ(0, close(bind_fd)); 925} 926 927FIXTURE(ipv4) 928{ 929 struct service_fixture srv0, srv1; 930}; 931 932FIXTURE_VARIANT(ipv4) 933{ 934 const enum sandbox_type sandbox; 935 const int type; 936}; 937 938/* clang-format off */ 939FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_tcp) { 940 /* clang-format on */ 941 .sandbox = NO_SANDBOX, 942 .type = SOCK_STREAM, 943}; 944 945/* clang-format off */ 946FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_tcp) { 947 /* clang-format on */ 948 .sandbox = TCP_SANDBOX, 949 .type = SOCK_STREAM, 950}; 951 952/* clang-format off */ 953FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_udp) { 954 /* clang-format on */ 955 .sandbox = NO_SANDBOX, 956 .type = SOCK_DGRAM, 957}; 958 959/* clang-format off */ 960FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_udp) { 961 /* clang-format on */ 962 .sandbox = TCP_SANDBOX, 963 .type = SOCK_DGRAM, 964}; 965 966FIXTURE_SETUP(ipv4) 967{ 968 const struct protocol_variant prot = { 969 .domain = AF_INET, 970 .type = variant->type, 971 }; 972 973 disable_caps(_metadata); 974 975 set_service(&self->srv0, prot, 0); 976 set_service(&self->srv1, prot, 1); 977 978 setup_loopback(_metadata); 979}; 980 981FIXTURE_TEARDOWN(ipv4) 982{ 983} 984 985TEST_F(ipv4, from_unix_to_inet) 986{ 987 int unix_stream_fd, unix_dgram_fd; 988 989 if (variant->sandbox == TCP_SANDBOX) { 990 const struct landlock_ruleset_attr ruleset_attr = { 991 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 992 LANDLOCK_ACCESS_NET_CONNECT_TCP, 993 }; 994 const struct landlock_net_port_attr tcp_bind_connect_p0 = { 995 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 996 LANDLOCK_ACCESS_NET_CONNECT_TCP, 997 .port = self->srv0.port, 998 }; 999 int ruleset_fd; 1000 1001 /* Denies connect and bind to check errno value. */ 1002 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1003 sizeof(ruleset_attr), 0); 1004 ASSERT_LE(0, ruleset_fd); 1005 1006 /* Allows connect and bind for srv0. */ 1007 ASSERT_EQ(0, 1008 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1009 &tcp_bind_connect_p0, 0)); 1010 1011 enforce_ruleset(_metadata, ruleset_fd); 1012 EXPECT_EQ(0, close(ruleset_fd)); 1013 } 1014 1015 unix_stream_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 1016 ASSERT_LE(0, unix_stream_fd); 1017 1018 unix_dgram_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); 1019 ASSERT_LE(0, unix_dgram_fd); 1020 1021 /* Checks unix stream bind and connect for srv0. */ 1022 EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv0)); 1023 EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv0)); 1024 1025 /* Checks unix stream bind and connect for srv1. */ 1026 EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv1)) 1027 { 1028 TH_LOG("Wrong bind error: %s", strerror(errno)); 1029 } 1030 EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv1)); 1031 1032 /* Checks unix datagram bind and connect for srv0. */ 1033 EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv0)); 1034 EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv0)); 1035 1036 /* Checks unix datagram bind and connect for srv1. */ 1037 EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv1)); 1038 EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv1)); 1039} 1040 1041FIXTURE(tcp_layers) 1042{ 1043 struct service_fixture srv0, srv1; 1044}; 1045 1046FIXTURE_VARIANT(tcp_layers) 1047{ 1048 const size_t num_layers; 1049 const int domain; 1050}; 1051 1052FIXTURE_SETUP(tcp_layers) 1053{ 1054 const struct protocol_variant prot = { 1055 .domain = variant->domain, 1056 .type = SOCK_STREAM, 1057 }; 1058 1059 disable_caps(_metadata); 1060 1061 ASSERT_EQ(0, set_service(&self->srv0, prot, 0)); 1062 ASSERT_EQ(0, set_service(&self->srv1, prot, 1)); 1063 1064 setup_loopback(_metadata); 1065}; 1066 1067FIXTURE_TEARDOWN(tcp_layers) 1068{ 1069} 1070 1071/* clang-format off */ 1072FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv4) { 1073 /* clang-format on */ 1074 .domain = AF_INET, 1075 .num_layers = 0, 1076}; 1077 1078/* clang-format off */ 1079FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv4) { 1080 /* clang-format on */ 1081 .domain = AF_INET, 1082 .num_layers = 1, 1083}; 1084 1085/* clang-format off */ 1086FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv4) { 1087 /* clang-format on */ 1088 .domain = AF_INET, 1089 .num_layers = 2, 1090}; 1091 1092/* clang-format off */ 1093FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv4) { 1094 /* clang-format on */ 1095 .domain = AF_INET, 1096 .num_layers = 3, 1097}; 1098 1099/* clang-format off */ 1100FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv6) { 1101 /* clang-format on */ 1102 .domain = AF_INET6, 1103 .num_layers = 0, 1104}; 1105 1106/* clang-format off */ 1107FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv6) { 1108 /* clang-format on */ 1109 .domain = AF_INET6, 1110 .num_layers = 1, 1111}; 1112 1113/* clang-format off */ 1114FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv6) { 1115 /* clang-format on */ 1116 .domain = AF_INET6, 1117 .num_layers = 2, 1118}; 1119 1120/* clang-format off */ 1121FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv6) { 1122 /* clang-format on */ 1123 .domain = AF_INET6, 1124 .num_layers = 3, 1125}; 1126 1127TEST_F(tcp_layers, ruleset_overlap) 1128{ 1129 const struct landlock_ruleset_attr ruleset_attr = { 1130 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1131 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1132 }; 1133 const struct landlock_net_port_attr tcp_bind = { 1134 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1135 .port = self->srv0.port, 1136 }; 1137 const struct landlock_net_port_attr tcp_bind_connect = { 1138 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1139 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1140 .port = self->srv0.port, 1141 }; 1142 1143 if (variant->num_layers >= 1) { 1144 int ruleset_fd; 1145 1146 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1147 sizeof(ruleset_attr), 0); 1148 ASSERT_LE(0, ruleset_fd); 1149 1150 /* Allows bind. */ 1151 ASSERT_EQ(0, 1152 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1153 &tcp_bind, 0)); 1154 /* Also allows bind, but allows connect too. */ 1155 ASSERT_EQ(0, 1156 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1157 &tcp_bind_connect, 0)); 1158 enforce_ruleset(_metadata, ruleset_fd); 1159 EXPECT_EQ(0, close(ruleset_fd)); 1160 } 1161 1162 if (variant->num_layers >= 2) { 1163 int ruleset_fd; 1164 1165 /* Creates another ruleset layer. */ 1166 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1167 sizeof(ruleset_attr), 0); 1168 ASSERT_LE(0, ruleset_fd); 1169 1170 /* Only allows bind. */ 1171 ASSERT_EQ(0, 1172 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1173 &tcp_bind, 0)); 1174 enforce_ruleset(_metadata, ruleset_fd); 1175 EXPECT_EQ(0, close(ruleset_fd)); 1176 } 1177 1178 if (variant->num_layers >= 3) { 1179 int ruleset_fd; 1180 1181 /* Creates another ruleset layer. */ 1182 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1183 sizeof(ruleset_attr), 0); 1184 ASSERT_LE(0, ruleset_fd); 1185 1186 /* Try to allow bind and connect. */ 1187 ASSERT_EQ(0, 1188 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1189 &tcp_bind_connect, 0)); 1190 enforce_ruleset(_metadata, ruleset_fd); 1191 EXPECT_EQ(0, close(ruleset_fd)); 1192 } 1193 1194 /* 1195 * Forbids to connect to the socket because only one ruleset layer 1196 * allows connect. 1197 */ 1198 test_bind_and_connect(_metadata, &self->srv0, false, 1199 variant->num_layers >= 2); 1200} 1201 1202TEST_F(tcp_layers, ruleset_expand) 1203{ 1204 if (variant->num_layers >= 1) { 1205 const struct landlock_ruleset_attr ruleset_attr = { 1206 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, 1207 }; 1208 /* Allows bind for srv0. */ 1209 const struct landlock_net_port_attr bind_srv0 = { 1210 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1211 .port = self->srv0.port, 1212 }; 1213 int ruleset_fd; 1214 1215 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1216 sizeof(ruleset_attr), 0); 1217 ASSERT_LE(0, ruleset_fd); 1218 ASSERT_EQ(0, 1219 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1220 &bind_srv0, 0)); 1221 enforce_ruleset(_metadata, ruleset_fd); 1222 EXPECT_EQ(0, close(ruleset_fd)); 1223 } 1224 1225 if (variant->num_layers >= 2) { 1226 /* Expands network mask with connect action. */ 1227 const struct landlock_ruleset_attr ruleset_attr = { 1228 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1229 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1230 }; 1231 /* Allows bind for srv0 and connect to srv0. */ 1232 const struct landlock_net_port_attr tcp_bind_connect_p0 = { 1233 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1234 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1235 .port = self->srv0.port, 1236 }; 1237 /* Try to allow bind for srv1. */ 1238 const struct landlock_net_port_attr tcp_bind_p1 = { 1239 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1240 .port = self->srv1.port, 1241 }; 1242 int ruleset_fd; 1243 1244 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1245 sizeof(ruleset_attr), 0); 1246 ASSERT_LE(0, ruleset_fd); 1247 ASSERT_EQ(0, 1248 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1249 &tcp_bind_connect_p0, 0)); 1250 ASSERT_EQ(0, 1251 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1252 &tcp_bind_p1, 0)); 1253 enforce_ruleset(_metadata, ruleset_fd); 1254 EXPECT_EQ(0, close(ruleset_fd)); 1255 } 1256 1257 if (variant->num_layers >= 3) { 1258 const struct landlock_ruleset_attr ruleset_attr = { 1259 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1260 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1261 }; 1262 /* Allows connect to srv0, without bind rule. */ 1263 const struct landlock_net_port_attr tcp_bind_p0 = { 1264 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1265 .port = self->srv0.port, 1266 }; 1267 int ruleset_fd; 1268 1269 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1270 sizeof(ruleset_attr), 0); 1271 ASSERT_LE(0, ruleset_fd); 1272 ASSERT_EQ(0, 1273 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1274 &tcp_bind_p0, 0)); 1275 enforce_ruleset(_metadata, ruleset_fd); 1276 EXPECT_EQ(0, close(ruleset_fd)); 1277 } 1278 1279 test_bind_and_connect(_metadata, &self->srv0, false, 1280 variant->num_layers >= 3); 1281 1282 test_bind_and_connect(_metadata, &self->srv1, variant->num_layers >= 1, 1283 variant->num_layers >= 2); 1284} 1285 1286/* clang-format off */ 1287FIXTURE(mini) {}; 1288/* clang-format on */ 1289 1290FIXTURE_SETUP(mini) 1291{ 1292 disable_caps(_metadata); 1293 1294 setup_loopback(_metadata); 1295}; 1296 1297FIXTURE_TEARDOWN(mini) 1298{ 1299} 1300 1301/* clang-format off */ 1302 1303#define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_TCP 1304 1305#define ACCESS_ALL ( \ 1306 LANDLOCK_ACCESS_NET_BIND_TCP | \ 1307 LANDLOCK_ACCESS_NET_CONNECT_TCP) 1308 1309/* clang-format on */ 1310 1311TEST_F(mini, network_access_rights) 1312{ 1313 const struct landlock_ruleset_attr ruleset_attr = { 1314 .handled_access_net = ACCESS_ALL, 1315 }; 1316 struct landlock_net_port_attr net_port = { 1317 .port = sock_port_start, 1318 }; 1319 int ruleset_fd; 1320 __u64 access; 1321 1322 ruleset_fd = 1323 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1324 ASSERT_LE(0, ruleset_fd); 1325 1326 for (access = 1; access <= ACCESS_LAST; access <<= 1) { 1327 net_port.allowed_access = access; 1328 EXPECT_EQ(0, 1329 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1330 &net_port, 0)) 1331 { 1332 TH_LOG("Failed to add rule with access 0x%llx: %s", 1333 access, strerror(errno)); 1334 } 1335 } 1336 EXPECT_EQ(0, close(ruleset_fd)); 1337} 1338 1339/* Checks invalid attribute, out of landlock network access range. */ 1340TEST_F(mini, ruleset_with_unknown_access) 1341{ 1342 __u64 access_mask; 1343 1344 for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST; 1345 access_mask >>= 1) { 1346 const struct landlock_ruleset_attr ruleset_attr = { 1347 .handled_access_net = access_mask, 1348 }; 1349 1350 EXPECT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 1351 sizeof(ruleset_attr), 0)); 1352 EXPECT_EQ(EINVAL, errno); 1353 } 1354} 1355 1356TEST_F(mini, rule_with_unknown_access) 1357{ 1358 const struct landlock_ruleset_attr ruleset_attr = { 1359 .handled_access_net = ACCESS_ALL, 1360 }; 1361 struct landlock_net_port_attr net_port = { 1362 .port = sock_port_start, 1363 }; 1364 int ruleset_fd; 1365 __u64 access; 1366 1367 ruleset_fd = 1368 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1369 ASSERT_LE(0, ruleset_fd); 1370 1371 for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) { 1372 net_port.allowed_access = access; 1373 EXPECT_EQ(-1, 1374 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1375 &net_port, 0)); 1376 EXPECT_EQ(EINVAL, errno); 1377 } 1378 EXPECT_EQ(0, close(ruleset_fd)); 1379} 1380 1381TEST_F(mini, rule_with_unhandled_access) 1382{ 1383 struct landlock_ruleset_attr ruleset_attr = { 1384 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, 1385 }; 1386 struct landlock_net_port_attr net_port = { 1387 .port = sock_port_start, 1388 }; 1389 int ruleset_fd; 1390 __u64 access; 1391 1392 ruleset_fd = 1393 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1394 ASSERT_LE(0, ruleset_fd); 1395 1396 for (access = 1; access > 0; access <<= 1) { 1397 int err; 1398 1399 net_port.allowed_access = access; 1400 err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1401 &net_port, 0); 1402 if (access == ruleset_attr.handled_access_net) { 1403 EXPECT_EQ(0, err); 1404 } else { 1405 EXPECT_EQ(-1, err); 1406 EXPECT_EQ(EINVAL, errno); 1407 } 1408 } 1409 1410 EXPECT_EQ(0, close(ruleset_fd)); 1411} 1412 1413TEST_F(mini, inval) 1414{ 1415 const struct landlock_ruleset_attr ruleset_attr = { 1416 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP 1417 }; 1418 const struct landlock_net_port_attr tcp_bind_connect = { 1419 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1420 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1421 .port = sock_port_start, 1422 }; 1423 const struct landlock_net_port_attr tcp_denied = { 1424 .allowed_access = 0, 1425 .port = sock_port_start, 1426 }; 1427 const struct landlock_net_port_attr tcp_bind = { 1428 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1429 .port = sock_port_start, 1430 }; 1431 int ruleset_fd; 1432 1433 ruleset_fd = 1434 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1435 ASSERT_LE(0, ruleset_fd); 1436 1437 /* Checks unhandled allowed_access. */ 1438 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1439 &tcp_bind_connect, 0)); 1440 EXPECT_EQ(EINVAL, errno); 1441 1442 /* Checks zero access value. */ 1443 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1444 &tcp_denied, 0)); 1445 EXPECT_EQ(ENOMSG, errno); 1446 1447 /* Adds with legitimate values. */ 1448 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1449 &tcp_bind, 0)); 1450} 1451 1452TEST_F(mini, tcp_port_overflow) 1453{ 1454 const struct landlock_ruleset_attr ruleset_attr = { 1455 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1456 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1457 }; 1458 const struct landlock_net_port_attr port_max_bind = { 1459 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1460 .port = UINT16_MAX, 1461 }; 1462 const struct landlock_net_port_attr port_max_connect = { 1463 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, 1464 .port = UINT16_MAX, 1465 }; 1466 const struct landlock_net_port_attr port_overflow1 = { 1467 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1468 .port = UINT16_MAX + 1, 1469 }; 1470 const struct landlock_net_port_attr port_overflow2 = { 1471 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1472 .port = UINT16_MAX + 2, 1473 }; 1474 const struct landlock_net_port_attr port_overflow3 = { 1475 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1476 .port = UINT32_MAX + 1UL, 1477 }; 1478 const struct landlock_net_port_attr port_overflow4 = { 1479 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1480 .port = UINT32_MAX + 2UL, 1481 }; 1482 const struct protocol_variant ipv4_tcp = { 1483 .domain = AF_INET, 1484 .type = SOCK_STREAM, 1485 }; 1486 struct service_fixture srv_denied, srv_max_allowed; 1487 int ruleset_fd; 1488 1489 ASSERT_EQ(0, set_service(&srv_denied, ipv4_tcp, 0)); 1490 1491 /* Be careful to avoid port inconsistencies. */ 1492 srv_max_allowed = srv_denied; 1493 srv_max_allowed.port = port_max_bind.port; 1494 srv_max_allowed.ipv4_addr.sin_port = htons(port_max_bind.port); 1495 1496 ruleset_fd = 1497 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1498 ASSERT_LE(0, ruleset_fd); 1499 1500 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1501 &port_max_bind, 0)); 1502 1503 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1504 &port_overflow1, 0)); 1505 EXPECT_EQ(EINVAL, errno); 1506 1507 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1508 &port_overflow2, 0)); 1509 EXPECT_EQ(EINVAL, errno); 1510 1511 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1512 &port_overflow3, 0)); 1513 EXPECT_EQ(EINVAL, errno); 1514 1515 /* Interleaves with invalid rule additions. */ 1516 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1517 &port_max_connect, 0)); 1518 1519 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1520 &port_overflow4, 0)); 1521 EXPECT_EQ(EINVAL, errno); 1522 1523 enforce_ruleset(_metadata, ruleset_fd); 1524 1525 test_bind_and_connect(_metadata, &srv_denied, true, true); 1526 test_bind_and_connect(_metadata, &srv_max_allowed, false, false); 1527} 1528 1529FIXTURE(ipv4_tcp) 1530{ 1531 struct service_fixture srv0, srv1; 1532}; 1533 1534FIXTURE_SETUP(ipv4_tcp) 1535{ 1536 const struct protocol_variant ipv4_tcp = { 1537 .domain = AF_INET, 1538 .type = SOCK_STREAM, 1539 }; 1540 1541 disable_caps(_metadata); 1542 1543 ASSERT_EQ(0, set_service(&self->srv0, ipv4_tcp, 0)); 1544 ASSERT_EQ(0, set_service(&self->srv1, ipv4_tcp, 1)); 1545 1546 setup_loopback(_metadata); 1547}; 1548 1549FIXTURE_TEARDOWN(ipv4_tcp) 1550{ 1551} 1552 1553TEST_F(ipv4_tcp, port_endianness) 1554{ 1555 const struct landlock_ruleset_attr ruleset_attr = { 1556 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1557 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1558 }; 1559 const struct landlock_net_port_attr bind_host_endian_p0 = { 1560 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1561 /* Host port format. */ 1562 .port = self->srv0.port, 1563 }; 1564 const struct landlock_net_port_attr connect_big_endian_p0 = { 1565 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, 1566 /* Big endian port format. */ 1567 .port = htons(self->srv0.port), 1568 }; 1569 const struct landlock_net_port_attr bind_connect_host_endian_p1 = { 1570 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1571 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1572 /* Host port format. */ 1573 .port = self->srv1.port, 1574 }; 1575 const unsigned int one = 1; 1576 const char little_endian = *(const char *)&one; 1577 int ruleset_fd; 1578 1579 ruleset_fd = 1580 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1581 ASSERT_LE(0, ruleset_fd); 1582 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1583 &bind_host_endian_p0, 0)); 1584 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1585 &connect_big_endian_p0, 0)); 1586 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1587 &bind_connect_host_endian_p1, 0)); 1588 enforce_ruleset(_metadata, ruleset_fd); 1589 1590 /* No restriction for big endinan CPU. */ 1591 test_bind_and_connect(_metadata, &self->srv0, false, little_endian); 1592 1593 /* No restriction for any CPU. */ 1594 test_bind_and_connect(_metadata, &self->srv1, false, false); 1595} 1596 1597TEST_F(ipv4_tcp, with_fs) 1598{ 1599 const struct landlock_ruleset_attr ruleset_attr_fs_net = { 1600 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR, 1601 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, 1602 }; 1603 struct landlock_path_beneath_attr path_beneath = { 1604 .allowed_access = LANDLOCK_ACCESS_FS_READ_DIR, 1605 .parent_fd = -1, 1606 }; 1607 struct landlock_net_port_attr tcp_bind = { 1608 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, 1609 .port = self->srv0.port, 1610 }; 1611 int ruleset_fd, bind_fd, dir_fd; 1612 1613 /* Creates ruleset both for filesystem and network access. */ 1614 ruleset_fd = landlock_create_ruleset(&ruleset_attr_fs_net, 1615 sizeof(ruleset_attr_fs_net), 0); 1616 ASSERT_LE(0, ruleset_fd); 1617 1618 /* Adds a filesystem rule. */ 1619 path_beneath.parent_fd = open("/dev", O_PATH | O_DIRECTORY | O_CLOEXEC); 1620 ASSERT_LE(0, path_beneath.parent_fd); 1621 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, 1622 &path_beneath, 0)); 1623 EXPECT_EQ(0, close(path_beneath.parent_fd)); 1624 1625 /* Adds a network rule. */ 1626 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1627 &tcp_bind, 0)); 1628 1629 enforce_ruleset(_metadata, ruleset_fd); 1630 EXPECT_EQ(0, close(ruleset_fd)); 1631 1632 /* Tests file access. */ 1633 dir_fd = open("/dev", O_RDONLY); 1634 EXPECT_LE(0, dir_fd); 1635 EXPECT_EQ(0, close(dir_fd)); 1636 1637 dir_fd = open("/", O_RDONLY); 1638 EXPECT_EQ(-1, dir_fd); 1639 EXPECT_EQ(EACCES, errno); 1640 1641 /* Tests port binding. */ 1642 bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); 1643 ASSERT_LE(0, bind_fd); 1644 EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); 1645 EXPECT_EQ(0, close(bind_fd)); 1646 1647 bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); 1648 ASSERT_LE(0, bind_fd); 1649 EXPECT_EQ(-EACCES, bind_variant(bind_fd, &self->srv1)); 1650} 1651 1652FIXTURE(port_specific) 1653{ 1654 struct service_fixture srv0; 1655}; 1656 1657FIXTURE_VARIANT(port_specific) 1658{ 1659 const enum sandbox_type sandbox; 1660 const struct protocol_variant prot; 1661}; 1662 1663/* clang-format off */ 1664FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv4) { 1665 /* clang-format on */ 1666 .sandbox = NO_SANDBOX, 1667 .prot = { 1668 .domain = AF_INET, 1669 .type = SOCK_STREAM, 1670 }, 1671}; 1672 1673/* clang-format off */ 1674FIXTURE_VARIANT_ADD(port_specific, sandbox_with_ipv4) { 1675 /* clang-format on */ 1676 .sandbox = TCP_SANDBOX, 1677 .prot = { 1678 .domain = AF_INET, 1679 .type = SOCK_STREAM, 1680 }, 1681}; 1682 1683/* clang-format off */ 1684FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv6) { 1685 /* clang-format on */ 1686 .sandbox = NO_SANDBOX, 1687 .prot = { 1688 .domain = AF_INET6, 1689 .type = SOCK_STREAM, 1690 }, 1691}; 1692 1693/* clang-format off */ 1694FIXTURE_VARIANT_ADD(port_specific, sandbox_with_ipv6) { 1695 /* clang-format on */ 1696 .sandbox = TCP_SANDBOX, 1697 .prot = { 1698 .domain = AF_INET6, 1699 .type = SOCK_STREAM, 1700 }, 1701}; 1702 1703FIXTURE_SETUP(port_specific) 1704{ 1705 disable_caps(_metadata); 1706 1707 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); 1708 1709 setup_loopback(_metadata); 1710}; 1711 1712FIXTURE_TEARDOWN(port_specific) 1713{ 1714} 1715 1716TEST_F(port_specific, bind_connect_zero) 1717{ 1718 int bind_fd, connect_fd, ret; 1719 uint16_t port; 1720 1721 /* Adds a rule layer with bind and connect actions. */ 1722 if (variant->sandbox == TCP_SANDBOX) { 1723 const struct landlock_ruleset_attr ruleset_attr = { 1724 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1725 LANDLOCK_ACCESS_NET_CONNECT_TCP 1726 }; 1727 const struct landlock_net_port_attr tcp_bind_connect_zero = { 1728 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1729 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1730 .port = 0, 1731 }; 1732 int ruleset_fd; 1733 1734 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1735 sizeof(ruleset_attr), 0); 1736 ASSERT_LE(0, ruleset_fd); 1737 1738 /* Checks zero port value on bind and connect actions. */ 1739 EXPECT_EQ(0, 1740 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1741 &tcp_bind_connect_zero, 0)); 1742 1743 enforce_ruleset(_metadata, ruleset_fd); 1744 EXPECT_EQ(0, close(ruleset_fd)); 1745 } 1746 1747 bind_fd = socket_variant(&self->srv0); 1748 ASSERT_LE(0, bind_fd); 1749 1750 connect_fd = socket_variant(&self->srv0); 1751 ASSERT_LE(0, connect_fd); 1752 1753 /* Sets address port to 0 for both protocol families. */ 1754 set_port(&self->srv0, 0); 1755 /* 1756 * Binds on port 0, which selects a random port within 1757 * ip_local_port_range. 1758 */ 1759 ret = bind_variant(bind_fd, &self->srv0); 1760 EXPECT_EQ(0, ret); 1761 1762 EXPECT_EQ(0, listen(bind_fd, backlog)); 1763 1764 /* Connects on port 0. */ 1765 ret = connect_variant(connect_fd, &self->srv0); 1766 EXPECT_EQ(-ECONNREFUSED, ret); 1767 1768 /* Sets binded port for both protocol families. */ 1769 port = get_binded_port(bind_fd, &variant->prot); 1770 EXPECT_NE(0, port); 1771 set_port(&self->srv0, port); 1772 /* Connects on the binded port. */ 1773 ret = connect_variant(connect_fd, &self->srv0); 1774 if (is_restricted(&variant->prot, variant->sandbox)) { 1775 /* Denied by Landlock. */ 1776 EXPECT_EQ(-EACCES, ret); 1777 } else { 1778 EXPECT_EQ(0, ret); 1779 } 1780 1781 EXPECT_EQ(0, close(connect_fd)); 1782 EXPECT_EQ(0, close(bind_fd)); 1783} 1784 1785TEST_F(port_specific, bind_connect_1023) 1786{ 1787 int bind_fd, connect_fd, ret; 1788 1789 /* Adds a rule layer with bind and connect actions. */ 1790 if (variant->sandbox == TCP_SANDBOX) { 1791 const struct landlock_ruleset_attr ruleset_attr = { 1792 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1793 LANDLOCK_ACCESS_NET_CONNECT_TCP 1794 }; 1795 /* A rule with port value less than 1024. */ 1796 const struct landlock_net_port_attr tcp_bind_connect_low_range = { 1797 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1798 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1799 .port = 1023, 1800 }; 1801 /* A rule with 1024 port. */ 1802 const struct landlock_net_port_attr tcp_bind_connect = { 1803 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | 1804 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1805 .port = 1024, 1806 }; 1807 int ruleset_fd; 1808 1809 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 1810 sizeof(ruleset_attr), 0); 1811 ASSERT_LE(0, ruleset_fd); 1812 1813 ASSERT_EQ(0, 1814 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1815 &tcp_bind_connect_low_range, 0)); 1816 ASSERT_EQ(0, 1817 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, 1818 &tcp_bind_connect, 0)); 1819 1820 enforce_ruleset(_metadata, ruleset_fd); 1821 EXPECT_EQ(0, close(ruleset_fd)); 1822 } 1823 1824 bind_fd = socket_variant(&self->srv0); 1825 ASSERT_LE(0, bind_fd); 1826 1827 connect_fd = socket_variant(&self->srv0); 1828 ASSERT_LE(0, connect_fd); 1829 1830 /* Sets address port to 1023 for both protocol families. */ 1831 set_port(&self->srv0, 1023); 1832 /* Binds on port 1023. */ 1833 ret = bind_variant(bind_fd, &self->srv0); 1834 /* Denied by the system. */ 1835 EXPECT_EQ(-EACCES, ret); 1836 1837 /* Binds on port 1023. */ 1838 set_cap(_metadata, CAP_NET_BIND_SERVICE); 1839 ret = bind_variant(bind_fd, &self->srv0); 1840 clear_cap(_metadata, CAP_NET_BIND_SERVICE); 1841 EXPECT_EQ(0, ret); 1842 EXPECT_EQ(0, listen(bind_fd, backlog)); 1843 1844 /* Connects on the binded port 1023. */ 1845 ret = connect_variant(connect_fd, &self->srv0); 1846 EXPECT_EQ(0, ret); 1847 1848 EXPECT_EQ(0, close(connect_fd)); 1849 EXPECT_EQ(0, close(bind_fd)); 1850 1851 bind_fd = socket_variant(&self->srv0); 1852 ASSERT_LE(0, bind_fd); 1853 1854 connect_fd = socket_variant(&self->srv0); 1855 ASSERT_LE(0, connect_fd); 1856 1857 /* Sets address port to 1024 for both protocol families. */ 1858 set_port(&self->srv0, 1024); 1859 /* Binds on port 1024. */ 1860 ret = bind_variant(bind_fd, &self->srv0); 1861 EXPECT_EQ(0, ret); 1862 EXPECT_EQ(0, listen(bind_fd, backlog)); 1863 1864 /* Connects on the binded port 1024. */ 1865 ret = connect_variant(connect_fd, &self->srv0); 1866 EXPECT_EQ(0, ret); 1867 1868 EXPECT_EQ(0, close(connect_fd)); 1869 EXPECT_EQ(0, close(bind_fd)); 1870} 1871 1872static int matches_log_tcp(const int audit_fd, const char *const blockers, 1873 const char *const dir_addr, const char *const addr, 1874 const char *const dir_port) 1875{ 1876 static const char log_template[] = REGEX_LANDLOCK_PREFIX 1877 " blockers=%s %s=%s %s=1024$"; 1878 /* 1879 * Max strlen(blockers): 16 1880 * Max strlen(dir_addr): 5 1881 * Max strlen(addr): 12 1882 * Max strlen(dir_port): 4 1883 */ 1884 char log_match[sizeof(log_template) + 37]; 1885 int log_match_len; 1886 1887 log_match_len = snprintf(log_match, sizeof(log_match), log_template, 1888 blockers, dir_addr, addr, dir_port); 1889 if (log_match_len > sizeof(log_match)) 1890 return -E2BIG; 1891 1892 return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match, 1893 NULL); 1894} 1895 1896FIXTURE(audit) 1897{ 1898 struct service_fixture srv0; 1899 struct audit_filter audit_filter; 1900 int audit_fd; 1901}; 1902 1903FIXTURE_VARIANT(audit) 1904{ 1905 const char *const addr; 1906 const struct protocol_variant prot; 1907}; 1908 1909/* clang-format off */ 1910FIXTURE_VARIANT_ADD(audit, ipv4) { 1911 /* clang-format on */ 1912 .addr = "127\\.0\\.0\\.1", 1913 .prot = { 1914 .domain = AF_INET, 1915 .type = SOCK_STREAM, 1916 }, 1917}; 1918 1919/* clang-format off */ 1920FIXTURE_VARIANT_ADD(audit, ipv6) { 1921 /* clang-format on */ 1922 .addr = "::1", 1923 .prot = { 1924 .domain = AF_INET6, 1925 .type = SOCK_STREAM, 1926 }, 1927}; 1928 1929FIXTURE_SETUP(audit) 1930{ 1931 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); 1932 setup_loopback(_metadata); 1933 1934 set_cap(_metadata, CAP_AUDIT_CONTROL); 1935 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter); 1936 EXPECT_LE(0, self->audit_fd); 1937 disable_caps(_metadata); 1938}; 1939 1940FIXTURE_TEARDOWN(audit) 1941{ 1942 set_cap(_metadata, CAP_AUDIT_CONTROL); 1943 EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter)); 1944 clear_cap(_metadata, CAP_AUDIT_CONTROL); 1945} 1946 1947TEST_F(audit, bind) 1948{ 1949 const struct landlock_ruleset_attr ruleset_attr = { 1950 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1951 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1952 }; 1953 struct audit_records records; 1954 int ruleset_fd, sock_fd; 1955 1956 ruleset_fd = 1957 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1958 ASSERT_LE(0, ruleset_fd); 1959 enforce_ruleset(_metadata, ruleset_fd); 1960 EXPECT_EQ(0, close(ruleset_fd)); 1961 1962 sock_fd = socket_variant(&self->srv0); 1963 ASSERT_LE(0, sock_fd); 1964 EXPECT_EQ(-EACCES, bind_variant(sock_fd, &self->srv0)); 1965 EXPECT_EQ(0, matches_log_tcp(self->audit_fd, "net\\.bind_tcp", "saddr", 1966 variant->addr, "src")); 1967 1968 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 1969 EXPECT_EQ(0, records.access); 1970 EXPECT_EQ(1, records.domain); 1971 1972 EXPECT_EQ(0, close(sock_fd)); 1973} 1974 1975TEST_F(audit, connect) 1976{ 1977 const struct landlock_ruleset_attr ruleset_attr = { 1978 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1979 LANDLOCK_ACCESS_NET_CONNECT_TCP, 1980 }; 1981 struct audit_records records; 1982 int ruleset_fd, sock_fd; 1983 1984 ruleset_fd = 1985 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1986 ASSERT_LE(0, ruleset_fd); 1987 enforce_ruleset(_metadata, ruleset_fd); 1988 EXPECT_EQ(0, close(ruleset_fd)); 1989 1990 sock_fd = socket_variant(&self->srv0); 1991 ASSERT_LE(0, sock_fd); 1992 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv0)); 1993 EXPECT_EQ(0, matches_log_tcp(self->audit_fd, "net\\.connect_tcp", 1994 "daddr", variant->addr, "dest")); 1995 1996 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 1997 EXPECT_EQ(0, records.access); 1998 EXPECT_EQ(1, records.domain); 1999 2000 EXPECT_EQ(0, close(sock_fd)); 2001} 2002 2003TEST_HARNESS_MAIN