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