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