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