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