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