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