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/in.h>
14 #include <linux/landlock.h>
15 #include <sched.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <sys/mount.h>
19 #include <sys/prctl.h>
20 #include <sys/socket.h>
21 #include <sys/syscall.h>
22 #include <sys/un.h>
23
24 #include "audit.h"
25 #include "common.h"
26 #include "trace.h"
27
28 #define TRACE_TASK "net_test"
29
30 const short sock_port_start = (1 << 10);
31
32 static const char loopback_ipv4[] = "127.0.0.1";
33 static const char loopback_ipv6[] = "::1";
34
35 /* Number pending connections queue to be hold. */
36 const short backlog = 10;
37
38 enum sandbox_type {
39 NO_SANDBOX,
40 /* This may be used to test rules that allow *and* deny accesses. */
41 TCP_SANDBOX,
42 UDP_SANDBOX,
43 };
44
set_service(struct service_fixture * const srv,const struct protocol_variant prot,const unsigned short index)45 static int set_service(struct service_fixture *const srv,
46 const struct protocol_variant prot,
47 const unsigned short index)
48 {
49 memset(srv, 0, sizeof(*srv));
50
51 /*
52 * Copies all protocol properties in case of the variant only contains
53 * a subset of them.
54 */
55 srv->protocol = prot;
56
57 /* Checks for port overflow. */
58 if (index > 2)
59 return 1;
60 srv->port = sock_port_start << (2 * index);
61
62 switch (prot.domain) {
63 case AF_UNSPEC:
64 case AF_INET:
65 srv->ipv4_addr.sin_family = prot.domain;
66 srv->ipv4_addr.sin_port = htons(srv->port);
67 srv->ipv4_addr.sin_addr.s_addr = inet_addr(loopback_ipv4);
68 return 0;
69
70 case AF_INET6:
71 srv->ipv6_addr.sin6_family = prot.domain;
72 srv->ipv6_addr.sin6_port = htons(srv->port);
73 inet_pton(AF_INET6, loopback_ipv6, &srv->ipv6_addr.sin6_addr);
74 return 0;
75
76 case AF_UNIX:
77 set_unix_address(srv, index);
78 return 0;
79 }
80 return 1;
81 }
82
setup_loopback(struct __test_metadata * const _metadata)83 static void setup_loopback(struct __test_metadata *const _metadata)
84 {
85 set_cap(_metadata, CAP_SYS_ADMIN);
86 ASSERT_EQ(0, unshare(CLONE_NEWNET));
87 clear_cap(_metadata, CAP_SYS_ADMIN);
88
89 set_ambient_cap(_metadata, CAP_NET_ADMIN);
90 ASSERT_EQ(0, system("ip link set dev lo up"));
91 clear_ambient_cap(_metadata, CAP_NET_ADMIN);
92 }
93
prot_is_tcp(const struct protocol_variant * const prot)94 static bool prot_is_tcp(const struct protocol_variant *const prot)
95 {
96 return (prot->domain == AF_INET || prot->domain == AF_INET6) &&
97 prot->type == SOCK_STREAM &&
98 (prot->protocol == IPPROTO_TCP || prot->protocol == IPPROTO_IP);
99 }
100
prot_is_udp(const struct protocol_variant * const prot)101 static bool prot_is_udp(const struct protocol_variant *const prot)
102 {
103 return (prot->domain == AF_INET || prot->domain == AF_INET6) &&
104 prot->type == SOCK_DGRAM &&
105 (prot->protocol == IPPROTO_UDP || prot->protocol == IPPROTO_IP);
106 }
107
is_restricted(const struct protocol_variant * const prot,const enum sandbox_type sandbox)108 static bool is_restricted(const struct protocol_variant *const prot,
109 const enum sandbox_type sandbox)
110 {
111 if (sandbox == TCP_SANDBOX)
112 return prot_is_tcp(prot);
113 else if (sandbox == UDP_SANDBOX)
114 return prot_is_udp(prot);
115 return false;
116 }
117
socket_variant(const struct service_fixture * const srv)118 static int socket_variant(const struct service_fixture *const srv)
119 {
120 /* Arbitrary value just to not block other tests indefinitely. */
121 const struct timeval timeout = {
122 .tv_sec = 0,
123 .tv_usec = 100000,
124 };
125 int sockfd;
126 int ret;
127
128 sockfd = socket(srv->protocol.domain, srv->protocol.type | SOCK_CLOEXEC,
129 srv->protocol.protocol);
130 if (sockfd < 0)
131 return -errno;
132
133 ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
134 sizeof(timeout));
135 if (ret != 0) {
136 ret = -errno;
137 close(sockfd);
138 return ret;
139 }
140 ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
141 sizeof(timeout));
142 if (ret != 0) {
143 ret = -errno;
144 close(sockfd);
145 return ret;
146 }
147 return sockfd;
148 }
149
150 #ifndef SIN6_LEN_RFC2133
151 #define SIN6_LEN_RFC2133 24
152 #endif
153
get_addrlen(const struct service_fixture * const srv,const bool minimal)154 static socklen_t get_addrlen(const struct service_fixture *const srv,
155 const bool minimal)
156 {
157 switch (srv->protocol.domain) {
158 case AF_UNSPEC:
159 if (minimal)
160 return sizeof(sa_family_t);
161 return sizeof(struct sockaddr_storage);
162
163 case AF_INET:
164 return sizeof(srv->ipv4_addr);
165
166 case AF_INET6:
167 if (minimal)
168 return SIN6_LEN_RFC2133;
169 return sizeof(srv->ipv6_addr);
170
171 case AF_UNIX:
172 if (minimal)
173 return sizeof(srv->unix_addr) -
174 sizeof(srv->unix_addr.sun_path);
175 return srv->unix_addr_len;
176
177 default:
178 return 0;
179 }
180 }
181
set_port(struct service_fixture * const srv,uint16_t port)182 static void set_port(struct service_fixture *const srv, uint16_t port)
183 {
184 switch (srv->protocol.domain) {
185 case AF_UNSPEC:
186 case AF_INET:
187 srv->ipv4_addr.sin_port = htons(port);
188 return;
189
190 case AF_INET6:
191 srv->ipv6_addr.sin6_port = htons(port);
192 return;
193
194 default:
195 return;
196 }
197 }
198
get_binded_port(int socket_fd,const struct protocol_variant * const prot)199 static uint16_t get_binded_port(int socket_fd,
200 const struct protocol_variant *const prot)
201 {
202 struct sockaddr_in ipv4_addr;
203 struct sockaddr_in6 ipv6_addr;
204 socklen_t ipv4_addr_len, ipv6_addr_len;
205
206 /* Gets binded port. */
207 switch (prot->domain) {
208 case AF_UNSPEC:
209 case AF_INET:
210 ipv4_addr_len = sizeof(ipv4_addr);
211 getsockname(socket_fd, &ipv4_addr, &ipv4_addr_len);
212 return ntohs(ipv4_addr.sin_port);
213
214 case AF_INET6:
215 ipv6_addr_len = sizeof(ipv6_addr);
216 getsockname(socket_fd, &ipv6_addr, &ipv6_addr_len);
217 return ntohs(ipv6_addr.sin6_port);
218
219 default:
220 return 0;
221 }
222 }
223
bind_variant_addrlen(const int sock_fd,const struct service_fixture * const srv,const socklen_t addrlen)224 static int bind_variant_addrlen(const int sock_fd,
225 const struct service_fixture *const srv,
226 const socklen_t addrlen)
227 {
228 int ret;
229
230 switch (srv->protocol.domain) {
231 case AF_UNSPEC:
232 case AF_INET:
233 ret = bind(sock_fd, &srv->ipv4_addr, addrlen);
234 break;
235
236 case AF_INET6:
237 ret = bind(sock_fd, &srv->ipv6_addr, addrlen);
238 break;
239
240 case AF_UNIX:
241 ret = bind(sock_fd, &srv->unix_addr, addrlen);
242 break;
243
244 default:
245 errno = EAFNOSUPPORT;
246 return -errno;
247 }
248
249 if (ret < 0)
250 return -errno;
251 return ret;
252 }
253
bind_variant(const int sock_fd,const struct service_fixture * const srv)254 static int bind_variant(const int sock_fd,
255 const struct service_fixture *const srv)
256 {
257 return bind_variant_addrlen(sock_fd, srv, get_addrlen(srv, false));
258 }
259
connect_variant_addrlen(const int sock_fd,const struct service_fixture * const srv,const socklen_t addrlen)260 static int connect_variant_addrlen(const int sock_fd,
261 const struct service_fixture *const srv,
262 const socklen_t addrlen)
263 {
264 int ret;
265
266 switch (srv->protocol.domain) {
267 case AF_UNSPEC:
268 case AF_INET:
269 ret = connect(sock_fd, &srv->ipv4_addr, addrlen);
270 break;
271
272 case AF_INET6:
273 ret = connect(sock_fd, &srv->ipv6_addr, addrlen);
274 break;
275
276 case AF_UNIX:
277 ret = connect(sock_fd, &srv->unix_addr, addrlen);
278 break;
279
280 default:
281 errno = -EAFNOSUPPORT;
282 return -errno;
283 }
284
285 if (ret < 0)
286 return -errno;
287 return ret;
288 }
289
connect_variant(const int sock_fd,const struct service_fixture * const srv)290 static int connect_variant(const int sock_fd,
291 const struct service_fixture *const srv)
292 {
293 return connect_variant_addrlen(sock_fd, srv, get_addrlen(srv, false));
294 }
295
sendto_variant_addrlen(const int sock_fd,const struct service_fixture * const srv,const socklen_t addrlen,void * buf,size_t len,size_t flags)296 static int sendto_variant_addrlen(const int sock_fd,
297 const struct service_fixture *const srv,
298 const socklen_t addrlen, void *buf,
299 size_t len, size_t flags)
300 {
301 const struct sockaddr *dst = NULL;
302 ssize_t ret;
303
304 /*
305 * We never want our processes to be killed by SIGPIPE: we check return
306 * codes and errno, so that we have actual error messages.
307 */
308 flags |= MSG_NOSIGNAL;
309
310 if (srv != NULL) {
311 switch (srv->protocol.domain) {
312 case AF_UNSPEC:
313 case AF_INET:
314 dst = (const struct sockaddr *)&srv->ipv4_addr;
315 break;
316
317 case AF_INET6:
318 dst = (const struct sockaddr *)&srv->ipv6_addr;
319 break;
320
321 case AF_UNIX:
322 dst = (const struct sockaddr *)&srv->unix_addr;
323 break;
324
325 default:
326 errno = EAFNOSUPPORT;
327 return -errno;
328 }
329 }
330
331 ret = sendto(sock_fd, buf, len, flags, dst, addrlen);
332 if (ret < 0)
333 return -errno;
334
335 /* errno is not set in cases of partial writes. */
336 if (ret != len)
337 return -EINTR;
338
339 return 0;
340 }
341
sendto_variant(const int sock_fd,const struct service_fixture * const srv,void * buf,size_t len,size_t flags)342 static int sendto_variant(const int sock_fd,
343 const struct service_fixture *const srv, void *buf,
344 size_t len, size_t flags)
345 {
346 socklen_t addrlen = 0;
347
348 if (srv != NULL)
349 addrlen = get_addrlen(srv, false);
350
351 return sendto_variant_addrlen(sock_fd, srv, addrlen, buf, len, flags);
352 }
353
test_sendmsg(struct __test_metadata * const _metadata,const struct protocol_variant * prot,int client_fd,int server_fd,const struct service_fixture * srv,bool bind_denied,bool send_denied)354 static int test_sendmsg(struct __test_metadata *const _metadata,
355 const struct protocol_variant *prot, int client_fd,
356 int server_fd, const struct service_fixture *srv,
357 bool bind_denied, bool send_denied)
358 {
359 int ret;
360 socklen_t opt_len;
361 int sock_type;
362 int addr_family;
363 struct sockaddr_storage peer_addr = { 0 };
364 bool has_remote_port;
365 bool needs_autobind;
366 char read_buf[1] = { 0 };
367
368 /*
369 * Prepare the test by inspecting the socket type and whether it has a
370 * local/remote address set (all of which determine the expected
371 * outcomes).
372 */
373 opt_len = sizeof(sock_type);
374 ASSERT_EQ(0, getsockopt(client_fd, SOL_SOCKET, SO_TYPE, &sock_type,
375 &opt_len));
376 opt_len = sizeof(addr_family);
377 ASSERT_EQ(0, getsockopt(client_fd, SOL_SOCKET, SO_DOMAIN, &addr_family,
378 &opt_len));
379 opt_len = sizeof(peer_addr);
380 has_remote_port = (getpeername(client_fd, (struct sockaddr *)&peer_addr,
381 &opt_len) == 0);
382 needs_autobind = (addr_family == AF_INET || addr_family == AF_INET6) &&
383 get_binded_port(client_fd, prot) == 0;
384
385 /* First, check error code with truncated explicit address. */
386 if (srv != NULL) {
387 ret = sendto_variant_addrlen(
388 client_fd, srv, get_addrlen(srv, true) - 1, "A", 1, 0);
389 if (sock_type == SOCK_STREAM && !has_remote_port) {
390 EXPECT_EQ(-EPIPE, ret)
391 {
392 return -1;
393 }
394 } else if (bind_denied && needs_autobind) {
395 EXPECT_EQ(-EACCES, ret)
396 {
397 return -1;
398 }
399 } else {
400 EXPECT_EQ(-EINVAL, ret)
401 {
402 return -1;
403 }
404 }
405 }
406
407 /* With or without explicit destination address (srv can be NULL). */
408 ret = sendto_variant(client_fd, srv, "B", 1, 0);
409 if (sock_type == SOCK_STREAM && !has_remote_port) {
410 EXPECT_EQ(-EPIPE, ret)
411 {
412 return -1;
413 }
414 } else if ((send_denied && srv != NULL) ||
415 (bind_denied && needs_autobind)) {
416 ASSERT_EQ(-EACCES, ret)
417 {
418 return -1;
419 }
420 } else if (srv == NULL && !has_remote_port) {
421 if (addr_family == AF_UNIX) {
422 ASSERT_EQ(-ENOTCONN, ret)
423 {
424 return -1;
425 }
426 } else if (sock_type == SOCK_STREAM) {
427 ASSERT_EQ(-EPIPE, ret)
428 {
429 return -1;
430 }
431 } else {
432 ASSERT_EQ(-EDESTADDRREQ, ret)
433 {
434 return -1;
435 }
436 }
437 } else {
438 ASSERT_EQ(0, ret);
439 ASSERT_EQ(1, recv(server_fd, read_buf, 1, 0));
440 ASSERT_EQ(read_buf[0], 'B')
441 {
442 return -1;
443 }
444 }
445
446 return 0;
447 }
448
FIXTURE(protocol)449 FIXTURE(protocol)
450 {
451 struct service_fixture srv0, srv1, srv2;
452 struct service_fixture unspec_any0, unspec_srv0, unspec_srv1;
453 };
454
FIXTURE_VARIANT(protocol)455 FIXTURE_VARIANT(protocol)
456 {
457 const enum sandbox_type sandbox;
458 const struct protocol_variant prot;
459 };
460
FIXTURE_SETUP(protocol)461 FIXTURE_SETUP(protocol)
462 {
463 struct protocol_variant prot_unspec = variant->prot;
464
465 prot_unspec.domain = AF_UNSPEC;
466
467 disable_caps(_metadata);
468
469 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0));
470 ASSERT_EQ(0, set_service(&self->srv1, variant->prot, 1));
471 ASSERT_EQ(0, set_service(&self->srv2, variant->prot, 2));
472
473 ASSERT_EQ(0, set_service(&self->unspec_srv0, prot_unspec, 0));
474 ASSERT_EQ(0, set_service(&self->unspec_srv1, prot_unspec, 1));
475
476 ASSERT_EQ(0, set_service(&self->unspec_any0, prot_unspec, 0));
477 self->unspec_any0.ipv4_addr.sin_addr.s_addr = htonl(INADDR_ANY);
478
479 setup_loopback(_metadata);
480 };
481
FIXTURE_TEARDOWN(protocol)482 FIXTURE_TEARDOWN(protocol)
483 {
484 }
485
486 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv4_tcp1)487 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_tcp1) {
488 /* clang-format on */
489 .sandbox = NO_SANDBOX,
490 .prot = {
491 .domain = AF_INET,
492 .type = SOCK_STREAM,
493 /* IPPROTO_IP == 0 */
494 .protocol = IPPROTO_IP,
495 },
496 };
497
498 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv4_tcp2)499 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_tcp2) {
500 /* clang-format on */
501 .sandbox = NO_SANDBOX,
502 .prot = {
503 .domain = AF_INET,
504 .type = SOCK_STREAM,
505 .protocol = IPPROTO_TCP,
506 },
507 };
508
509 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv4_mptcp)510 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_mptcp) {
511 /* clang-format on */
512 .sandbox = NO_SANDBOX,
513 .prot = {
514 .domain = AF_INET,
515 .type = SOCK_STREAM,
516 .protocol = IPPROTO_MPTCP,
517 },
518 };
519
520 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv6_tcp1)521 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_tcp1) {
522 /* clang-format on */
523 .sandbox = NO_SANDBOX,
524 .prot = {
525 .domain = AF_INET6,
526 .type = SOCK_STREAM,
527 /* IPPROTO_IP == 0 */
528 .protocol = IPPROTO_IP,
529 },
530 };
531
532 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv6_tcp2)533 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_tcp2) {
534 /* clang-format on */
535 .sandbox = NO_SANDBOX,
536 .prot = {
537 .domain = AF_INET6,
538 .type = SOCK_STREAM,
539 .protocol = IPPROTO_TCP,
540 },
541 };
542
543 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv6_mptcp)544 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_mptcp) {
545 /* clang-format on */
546 .sandbox = NO_SANDBOX,
547 .prot = {
548 .domain = AF_INET6,
549 .type = SOCK_STREAM,
550 .protocol = IPPROTO_MPTCP,
551 },
552 };
553
554 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv4_udp)555 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_udp) {
556 /* clang-format on */
557 .sandbox = NO_SANDBOX,
558 .prot = {
559 .domain = AF_INET,
560 .type = SOCK_DGRAM,
561 },
562 };
563
564 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_ipv6_udp)565 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_udp) {
566 /* clang-format on */
567 .sandbox = NO_SANDBOX,
568 .prot = {
569 .domain = AF_INET6,
570 .type = SOCK_DGRAM,
571 },
572 };
573
574 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_unix_stream)575 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_stream) {
576 /* clang-format on */
577 .sandbox = NO_SANDBOX,
578 .prot = {
579 .domain = AF_UNIX,
580 .type = SOCK_STREAM,
581 },
582 };
583
584 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,no_sandbox_with_unix_datagram)585 FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_datagram) {
586 /* clang-format on */
587 .sandbox = NO_SANDBOX,
588 .prot = {
589 .domain = AF_UNIX,
590 .type = SOCK_DGRAM,
591 },
592 };
593
594 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv4_tcp1)595 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_tcp1) {
596 /* clang-format on */
597 .sandbox = TCP_SANDBOX,
598 .prot = {
599 .domain = AF_INET,
600 .type = SOCK_STREAM,
601 /* IPPROTO_IP == 0 */
602 .protocol = IPPROTO_IP,
603 },
604 };
605
606 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv4_tcp2)607 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_tcp2) {
608 /* clang-format on */
609 .sandbox = TCP_SANDBOX,
610 .prot = {
611 .domain = AF_INET,
612 .type = SOCK_STREAM,
613 .protocol = IPPROTO_TCP,
614 },
615 };
616
617 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv4_mptcp)618 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_mptcp) {
619 /* clang-format on */
620 .sandbox = TCP_SANDBOX,
621 .prot = {
622 .domain = AF_INET,
623 .type = SOCK_STREAM,
624 .protocol = IPPROTO_MPTCP,
625 },
626 };
627
628 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv6_tcp1)629 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_tcp1) {
630 /* clang-format on */
631 .sandbox = TCP_SANDBOX,
632 .prot = {
633 .domain = AF_INET6,
634 .type = SOCK_STREAM,
635 /* IPPROTO_IP == 0 */
636 .protocol = IPPROTO_IP,
637 },
638 };
639
640 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv6_tcp2)641 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_tcp2) {
642 /* clang-format on */
643 .sandbox = TCP_SANDBOX,
644 .prot = {
645 .domain = AF_INET6,
646 .type = SOCK_STREAM,
647 .protocol = IPPROTO_TCP,
648 },
649 };
650
651 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv6_mptcp)652 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_mptcp) {
653 /* clang-format on */
654 .sandbox = TCP_SANDBOX,
655 .prot = {
656 .domain = AF_INET6,
657 .type = SOCK_STREAM,
658 .protocol = IPPROTO_MPTCP,
659 },
660 };
661
662 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv4_udp)663 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_udp) {
664 /* clang-format on */
665 .sandbox = TCP_SANDBOX,
666 .prot = {
667 .domain = AF_INET,
668 .type = SOCK_DGRAM,
669 },
670 };
671
672 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_ipv6_udp)673 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_udp) {
674 /* clang-format on */
675 .sandbox = TCP_SANDBOX,
676 .prot = {
677 .domain = AF_INET6,
678 .type = SOCK_DGRAM,
679 },
680 };
681
682 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_unix_stream)683 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_stream) {
684 /* clang-format on */
685 .sandbox = TCP_SANDBOX,
686 .prot = {
687 .domain = AF_UNIX,
688 .type = SOCK_STREAM,
689 },
690 };
691
692 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,tcp_sandbox_with_unix_datagram)693 FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_datagram) {
694 /* clang-format on */
695 .sandbox = TCP_SANDBOX,
696 .prot = {
697 .domain = AF_UNIX,
698 .type = SOCK_DGRAM,
699 },
700 };
701
702 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv4_udp1)703 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv4_udp1) {
704 /* clang-format on */
705 .sandbox = UDP_SANDBOX,
706 .prot = {
707 .domain = AF_INET,
708 .type = SOCK_DGRAM,
709 .protocol = IPPROTO_UDP,
710 },
711 };
712
713 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv4_udp2)714 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv4_udp2) {
715 /* clang-format on */
716 .sandbox = UDP_SANDBOX,
717 .prot = {
718 .domain = AF_INET,
719 .type = SOCK_DGRAM,
720 /* IPPROTO_IP == 0 */
721 .protocol = IPPROTO_IP,
722 },
723 };
724
725 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv6_udp1)726 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv6_udp1) {
727 /* clang-format on */
728 .sandbox = UDP_SANDBOX,
729 .prot = {
730 .domain = AF_INET6,
731 .type = SOCK_DGRAM,
732 .protocol = IPPROTO_UDP,
733 },
734 };
735
736 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv6_udp2)737 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv6_udp2) {
738 /* clang-format on */
739 .sandbox = UDP_SANDBOX,
740 .prot = {
741 .domain = AF_INET6,
742 .type = SOCK_DGRAM,
743 /* IPPROTO_IP == 0 */
744 .protocol = IPPROTO_IP,
745 },
746 };
747
748 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv4_tcp)749 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv4_tcp) {
750 /* clang-format on */
751 .sandbox = UDP_SANDBOX,
752 .prot = {
753 .domain = AF_INET,
754 .type = SOCK_STREAM,
755 },
756 };
757
758 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_ipv6_tcp)759 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_ipv6_tcp) {
760 /* clang-format on */
761 .sandbox = UDP_SANDBOX,
762 .prot = {
763 .domain = AF_INET6,
764 .type = SOCK_STREAM,
765 },
766 };
767
768 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_unix_stream)769 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_unix_stream) {
770 /* clang-format on */
771 .sandbox = UDP_SANDBOX,
772 .prot = {
773 .domain = AF_UNIX,
774 .type = SOCK_STREAM,
775 },
776 };
777
778 /* clang-format off */
FIXTURE_VARIANT_ADD(protocol,udp_sandbox_with_unix_datagram)779 FIXTURE_VARIANT_ADD(protocol, udp_sandbox_with_unix_datagram) {
780 /* clang-format on */
781 .sandbox = UDP_SANDBOX,
782 .prot = {
783 .domain = AF_UNIX,
784 .type = SOCK_DGRAM,
785 },
786 };
787
test_bind_and_connect(struct __test_metadata * const _metadata,const struct service_fixture * const srv,const bool deny_bind,const bool deny_connect)788 static void test_bind_and_connect(struct __test_metadata *const _metadata,
789 const struct service_fixture *const srv,
790 const bool deny_bind, const bool deny_connect)
791 {
792 char buf = '\0';
793 int inval_fd, bind_fd, client_fd, status, ret;
794 pid_t child;
795
796 /* Starts invalid addrlen tests with bind. */
797 inval_fd = socket_variant(srv);
798 ASSERT_LE(0, inval_fd)
799 {
800 TH_LOG("Failed to create socket: %s", strerror(errno));
801 }
802
803 /* Tries to bind with zero as addrlen. */
804 EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv, 0));
805
806 /* Tries to bind with too small addrlen. */
807 EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv,
808 get_addrlen(srv, true) - 1));
809
810 /* Tries to bind with minimal addrlen. */
811 ret = bind_variant_addrlen(inval_fd, srv, get_addrlen(srv, true));
812 if (deny_bind) {
813 EXPECT_EQ(-EACCES, ret);
814 } else {
815 EXPECT_EQ(0, ret)
816 {
817 TH_LOG("Failed to bind to socket: %s", strerror(errno));
818 }
819 }
820 EXPECT_EQ(0, close(inval_fd));
821
822 /* Starts invalid addrlen tests with connect. */
823 inval_fd = socket_variant(srv);
824 ASSERT_LE(0, inval_fd);
825
826 /* Tries to connect with zero as addrlen. */
827 EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv, 0));
828
829 /* Tries to connect with too small addrlen. */
830 EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv,
831 get_addrlen(srv, true) - 1));
832
833 /* Tries to connect with minimal addrlen. */
834 ret = connect_variant_addrlen(inval_fd, srv, get_addrlen(srv, true));
835 if (srv->protocol.domain == AF_UNIX) {
836 EXPECT_EQ(-EINVAL, ret);
837 } else if (deny_connect) {
838 EXPECT_EQ(-EACCES, ret);
839 } else if (srv->protocol.type == SOCK_STREAM) {
840 /* No listening server, whatever the value of deny_bind. */
841 EXPECT_EQ(-ECONNREFUSED, ret);
842 } else {
843 EXPECT_EQ(0, ret)
844 {
845 TH_LOG("Failed to connect to socket: %s",
846 strerror(errno));
847 }
848 }
849 EXPECT_EQ(0, close(inval_fd));
850
851 /* Starts connection tests. */
852 bind_fd = socket_variant(srv);
853 ASSERT_LE(0, bind_fd);
854
855 ret = bind_variant(bind_fd, srv);
856 if (deny_bind) {
857 EXPECT_EQ(-EACCES, ret);
858 } else {
859 EXPECT_EQ(0, ret);
860
861 /* Creates a listening socket. */
862 if (srv->protocol.type == SOCK_STREAM)
863 EXPECT_EQ(0, listen(bind_fd, backlog));
864 }
865
866 child = fork();
867 ASSERT_LE(0, child);
868 if (child == 0) {
869 int connect_fd, ret;
870
871 /* Closes listening socket for the child. */
872 EXPECT_EQ(0, close(bind_fd));
873
874 /* Starts connection tests. */
875 connect_fd = socket_variant(srv);
876 ASSERT_LE(0, connect_fd);
877 ret = connect_variant(connect_fd, srv);
878 if (deny_connect) {
879 EXPECT_EQ(-EACCES, ret);
880 } else if (deny_bind && srv->protocol.type == SOCK_STREAM) {
881 /* No listening server. */
882 EXPECT_EQ(-ECONNREFUSED, ret);
883 } else {
884 EXPECT_EQ(0, ret);
885 EXPECT_EQ(1, write(connect_fd, ".", 1));
886 }
887
888 EXPECT_EQ(0, close(connect_fd));
889 _exit(_metadata->exit_code);
890 return;
891 }
892
893 /* Accepts connection from the child. */
894 client_fd = bind_fd;
895 if (!deny_bind && !deny_connect) {
896 if (srv->protocol.type == SOCK_STREAM) {
897 client_fd = accept(bind_fd, NULL, 0);
898 ASSERT_LE(0, client_fd);
899 }
900
901 EXPECT_EQ(1, read(client_fd, &buf, 1));
902 EXPECT_EQ('.', buf);
903 }
904
905 EXPECT_EQ(child, waitpid(child, &status, 0));
906 EXPECT_EQ(1, WIFEXITED(status));
907 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
908
909 /* Closes connection, if any. */
910 if (client_fd != bind_fd)
911 EXPECT_LE(0, close(client_fd));
912
913 /* Closes listening socket. */
914 EXPECT_EQ(0, close(bind_fd));
915 }
916
TEST_F(protocol,bind)917 TEST_F(protocol, bind)
918 {
919 if (variant->sandbox == TCP_SANDBOX ||
920 variant->sandbox == UDP_SANDBOX) {
921 const __u64 bind_access =
922 (variant->sandbox == TCP_SANDBOX ?
923 LANDLOCK_ACCESS_NET_BIND_TCP :
924 LANDLOCK_ACCESS_NET_BIND_UDP);
925 const __u64 conn_access =
926 (variant->sandbox == TCP_SANDBOX ?
927 LANDLOCK_ACCESS_NET_CONNECT_TCP :
928 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
929 const struct landlock_ruleset_attr ruleset_attr = {
930 .handled_access_net = bind_access | conn_access,
931 };
932 const struct landlock_net_port_attr bind_connect_p0 = {
933 .allowed_access = bind_access | conn_access,
934 .port = self->srv0.port,
935 };
936 const struct landlock_net_port_attr connect_p1 = {
937 .allowed_access = conn_access,
938 .port = self->srv1.port,
939 };
940 int ruleset_fd;
941
942 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
943 sizeof(ruleset_attr), 0);
944 ASSERT_LE(0, ruleset_fd);
945
946 /* Allows connect and bind for the first port. */
947 ASSERT_EQ(0,
948 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
949 &bind_connect_p0, 0));
950
951 /* Allows connect and denies bind for the second port. */
952 ASSERT_EQ(0,
953 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
954 &connect_p1, 0));
955
956 /*
957 * For UDP sockets, allows binding to ephemeral ports (required
958 * to connect or send a first datagram)
959 */
960 if (variant->sandbox == UDP_SANDBOX) {
961 const struct landlock_net_port_attr bind_ephemeral = {
962 .allowed_access = bind_access,
963 .port = 0,
964 };
965 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
966 LANDLOCK_RULE_NET_PORT,
967 &bind_ephemeral, 0));
968 }
969
970 enforce_ruleset(_metadata, ruleset_fd);
971 EXPECT_EQ(0, close(ruleset_fd));
972 }
973
974 /* Binds a socket to the first port. */
975 test_bind_and_connect(_metadata, &self->srv0, false, false);
976
977 /* Binds a socket to the second port. */
978 test_bind_and_connect(_metadata, &self->srv1,
979 is_restricted(&variant->prot, variant->sandbox),
980 false);
981
982 /* Binds a socket to the third port. */
983 test_bind_and_connect(_metadata, &self->srv2,
984 is_restricted(&variant->prot, variant->sandbox),
985 is_restricted(&variant->prot, variant->sandbox));
986 }
987
TEST_F(protocol,connect)988 TEST_F(protocol, connect)
989 {
990 if (variant->sandbox == TCP_SANDBOX ||
991 variant->sandbox == UDP_SANDBOX) {
992 const __u64 bind_access =
993 (variant->sandbox == TCP_SANDBOX ?
994 LANDLOCK_ACCESS_NET_BIND_TCP :
995 LANDLOCK_ACCESS_NET_BIND_UDP);
996 const __u64 conn_access =
997 (variant->sandbox == TCP_SANDBOX ?
998 LANDLOCK_ACCESS_NET_CONNECT_TCP :
999 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
1000 const struct landlock_ruleset_attr ruleset_attr = {
1001 .handled_access_net = bind_access | conn_access,
1002 };
1003 const struct landlock_net_port_attr bind_connect_p0 = {
1004 .allowed_access = bind_access | conn_access,
1005 .port = self->srv0.port,
1006 };
1007 const struct landlock_net_port_attr bind_p1 = {
1008 .allowed_access = bind_access,
1009 .port = self->srv1.port,
1010 };
1011 int ruleset_fd;
1012
1013 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
1014 sizeof(ruleset_attr), 0);
1015 ASSERT_LE(0, ruleset_fd);
1016
1017 /* Allows connect and bind for the first port. */
1018 ASSERT_EQ(0,
1019 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
1020 &bind_connect_p0, 0));
1021
1022 /* Allows bind and denies connect for the second port. */
1023 ASSERT_EQ(0,
1024 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
1025 &bind_p1, 0));
1026
1027 /*
1028 * For UDP sockets, allows binding to ephemeral ports (required
1029 * to connect or send a first datagram)
1030 */
1031 if (variant->sandbox == UDP_SANDBOX) {
1032 const struct landlock_net_port_attr bind_ephemeral = {
1033 .allowed_access = bind_access,
1034 .port = 0,
1035 };
1036 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
1037 LANDLOCK_RULE_NET_PORT,
1038 &bind_ephemeral, 0));
1039 }
1040
1041 enforce_ruleset(_metadata, ruleset_fd);
1042 EXPECT_EQ(0, close(ruleset_fd));
1043 }
1044
1045 test_bind_and_connect(_metadata, &self->srv0, false, false);
1046
1047 test_bind_and_connect(_metadata, &self->srv1, false,
1048 is_restricted(&variant->prot, variant->sandbox));
1049
1050 test_bind_and_connect(_metadata, &self->srv2,
1051 is_restricted(&variant->prot, variant->sandbox),
1052 is_restricted(&variant->prot, variant->sandbox));
1053 }
1054
TEST_F(protocol,bind_unspec)1055 TEST_F(protocol, bind_unspec)
1056 {
1057 const __u64 bind_access = (variant->sandbox == TCP_SANDBOX ?
1058 LANDLOCK_ACCESS_NET_BIND_TCP :
1059 LANDLOCK_ACCESS_NET_BIND_UDP);
1060 const struct landlock_ruleset_attr ruleset_attr = {
1061 .handled_access_net = bind_access,
1062 };
1063 const struct landlock_net_port_attr rule_bind = {
1064 .allowed_access = bind_access,
1065 .port = self->srv0.port,
1066 };
1067 int bind_fd, ret;
1068
1069 if (variant->sandbox == TCP_SANDBOX ||
1070 variant->sandbox == UDP_SANDBOX) {
1071 const int ruleset_fd = landlock_create_ruleset(
1072 &ruleset_attr, sizeof(ruleset_attr), 0);
1073 ASSERT_LE(0, ruleset_fd);
1074
1075 /* Allows bind. */
1076 ASSERT_EQ(0,
1077 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
1078 &rule_bind, 0));
1079 enforce_ruleset(_metadata, ruleset_fd);
1080 EXPECT_EQ(0, close(ruleset_fd));
1081 }
1082
1083 bind_fd = socket_variant(&self->srv0);
1084 ASSERT_LE(0, bind_fd);
1085
1086 /* Tries to bind with too small addrlen. */
1087 EXPECT_EQ(-EINVAL, bind_variant_addrlen(
1088 bind_fd, &self->unspec_any0,
1089 get_addrlen(&self->unspec_any0, true) - 1));
1090
1091 /* Allowed bind on AF_UNSPEC/INADDR_ANY. */
1092 ret = bind_variant(bind_fd, &self->unspec_any0);
1093 if (variant->prot.domain == AF_INET) {
1094 EXPECT_EQ(0, ret)
1095 {
1096 TH_LOG("Failed to bind to unspec/any socket: %s",
1097 strerror(errno));
1098 }
1099 } else if (variant->prot.domain == AF_INET6) {
1100 EXPECT_EQ(-EAFNOSUPPORT, ret);
1101 } else {
1102 EXPECT_EQ(-EINVAL, ret);
1103 }
1104 EXPECT_EQ(0, close(bind_fd));
1105
1106 if (variant->sandbox == TCP_SANDBOX ||
1107 variant->sandbox == UDP_SANDBOX) {
1108 const int ruleset_fd = landlock_create_ruleset(
1109 &ruleset_attr, sizeof(ruleset_attr), 0);
1110 ASSERT_LE(0, ruleset_fd);
1111
1112 /* Denies bind. */
1113 enforce_ruleset(_metadata, ruleset_fd);
1114 EXPECT_EQ(0, close(ruleset_fd));
1115 }
1116
1117 bind_fd = socket_variant(&self->srv0);
1118 ASSERT_LE(0, bind_fd);
1119
1120 /* Denied bind on AF_UNSPEC/INADDR_ANY. */
1121 ret = bind_variant(bind_fd, &self->unspec_any0);
1122 if (variant->prot.domain == AF_INET) {
1123 if (is_restricted(&variant->prot, variant->sandbox)) {
1124 EXPECT_EQ(-EACCES, ret);
1125 } else {
1126 EXPECT_EQ(0, ret);
1127 }
1128 } else if (variant->prot.domain == AF_INET6) {
1129 EXPECT_EQ(-EAFNOSUPPORT, ret);
1130 } else {
1131 EXPECT_EQ(-EINVAL, ret);
1132 }
1133 EXPECT_EQ(0, close(bind_fd));
1134
1135 /* Checks bind with AF_UNSPEC and the loopback address. */
1136 bind_fd = socket_variant(&self->srv0);
1137 ASSERT_LE(0, bind_fd);
1138 ret = bind_variant(bind_fd, &self->unspec_srv0);
1139 if (variant->prot.domain == AF_INET ||
1140 variant->prot.domain == AF_INET6) {
1141 EXPECT_EQ(-EAFNOSUPPORT, ret);
1142 } else {
1143 EXPECT_EQ(-EINVAL, ret)
1144 {
1145 TH_LOG("Wrong bind error: %s", strerror(errno));
1146 }
1147 }
1148 EXPECT_EQ(0, close(bind_fd));
1149 }
1150
TEST_F(protocol,connect_unspec)1151 TEST_F(protocol, connect_unspec)
1152 {
1153 const __u64 connect_right =
1154 (variant->sandbox == TCP_SANDBOX ?
1155 LANDLOCK_ACCESS_NET_CONNECT_TCP :
1156 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
1157 const __u64 bind_right = (variant->sandbox == TCP_SANDBOX ?
1158 LANDLOCK_ACCESS_NET_BIND_TCP :
1159 LANDLOCK_ACCESS_NET_BIND_UDP);
1160 const struct landlock_ruleset_attr ruleset_conn = {
1161 .handled_access_net = connect_right,
1162 };
1163 const struct landlock_ruleset_attr ruleset_conn_bind = {
1164 .handled_access_net = connect_right | bind_right,
1165 };
1166 const struct landlock_net_port_attr rule_connect = {
1167 .allowed_access = connect_right,
1168 .port = self->srv0.port,
1169 };
1170 int bind_fd, client_fd, status;
1171 pid_t child;
1172
1173 /* Specific connection tests. */
1174 bind_fd = socket_variant(&self->srv0);
1175 ASSERT_LE(0, bind_fd);
1176 EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0));
1177 if (self->srv0.protocol.type == SOCK_STREAM)
1178 EXPECT_EQ(0, listen(bind_fd, backlog));
1179
1180 child = fork();
1181 ASSERT_LE(0, child);
1182 if (child == 0) {
1183 int connect_fd, ret;
1184
1185 /* Closes listening socket for the child. */
1186 EXPECT_EQ(0, close(bind_fd));
1187
1188 connect_fd = socket_variant(&self->srv0);
1189 ASSERT_LE(0, connect_fd);
1190 EXPECT_EQ(0, connect_variant(connect_fd, &self->srv0));
1191
1192 /* Tries to connect again, or set peer. */
1193 ret = connect_variant(connect_fd, &self->srv0);
1194 if (self->srv0.protocol.type == SOCK_STREAM) {
1195 EXPECT_EQ(-EISCONN, ret);
1196 } else {
1197 EXPECT_EQ(0, ret);
1198 }
1199
1200 if (variant->sandbox == TCP_SANDBOX ||
1201 variant->sandbox == UDP_SANDBOX) {
1202 const int ruleset_fd = landlock_create_ruleset(
1203 &ruleset_conn, sizeof(ruleset_conn), 0);
1204 ASSERT_LE(0, ruleset_fd);
1205
1206 /* Allows connect. */
1207 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
1208 LANDLOCK_RULE_NET_PORT,
1209 &rule_connect, 0));
1210 enforce_ruleset(_metadata, ruleset_fd);
1211 EXPECT_EQ(0, close(ruleset_fd));
1212 }
1213
1214 /* Disconnects already connected socket, or set peer. */
1215 ret = connect_variant(connect_fd, &self->unspec_any0);
1216 if (self->srv0.protocol.domain == AF_UNIX &&
1217 self->srv0.protocol.type == SOCK_STREAM) {
1218 EXPECT_EQ(-EINVAL, ret);
1219 } else {
1220 EXPECT_EQ(0, ret);
1221 }
1222
1223 /* Tries to reconnect, or set peer. */
1224 ret = connect_variant(connect_fd, &self->srv0);
1225 if (self->srv0.protocol.domain == AF_UNIX &&
1226 self->srv0.protocol.type == SOCK_STREAM) {
1227 EXPECT_EQ(-EISCONN, ret);
1228 } else {
1229 EXPECT_EQ(0, ret);
1230 }
1231
1232 if (variant->sandbox == TCP_SANDBOX ||
1233 variant->sandbox == UDP_SANDBOX) {
1234 const int ruleset_fd = landlock_create_ruleset(
1235 &ruleset_conn_bind, sizeof(ruleset_conn_bind),
1236 0);
1237 ASSERT_LE(0, ruleset_fd);
1238
1239 /* Denies connect and bind. */
1240 enforce_ruleset(_metadata, ruleset_fd);
1241 EXPECT_EQ(0, close(ruleset_fd));
1242 }
1243
1244 /* Try to re-disconnect with a truncated address struct. */
1245 EXPECT_EQ(-EINVAL,
1246 connect_variant_addrlen(
1247 connect_fd, &self->unspec_any0,
1248 get_addrlen(&self->unspec_any0, true) - 1));
1249
1250 /*
1251 * Re-disconnect, with a minimal sockaddr struct (just a
1252 * bare af_family=AF_UNSPEC field).
1253 */
1254 ret = connect_variant_addrlen(connect_fd, &self->unspec_any0,
1255 get_addrlen(&self->unspec_any0,
1256 true));
1257 if (self->srv0.protocol.domain == AF_UNIX &&
1258 self->srv0.protocol.type == SOCK_STREAM) {
1259 EXPECT_EQ(-EINVAL, ret);
1260 } else {
1261 /* Always allowed to disconnect. */
1262 EXPECT_EQ(0, ret);
1263 }
1264
1265 EXPECT_EQ(0, close(connect_fd));
1266 _exit(_metadata->exit_code);
1267 return;
1268 }
1269
1270 client_fd = bind_fd;
1271 if (self->srv0.protocol.type == SOCK_STREAM) {
1272 client_fd = accept(bind_fd, NULL, 0);
1273 ASSERT_LE(0, client_fd);
1274 }
1275
1276 EXPECT_EQ(child, waitpid(child, &status, 0));
1277 EXPECT_EQ(1, WIFEXITED(status));
1278 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1279
1280 /* Closes connection, if any. */
1281 if (client_fd != bind_fd)
1282 EXPECT_LE(0, close(client_fd));
1283
1284 /* Closes listening socket. */
1285 EXPECT_EQ(0, close(bind_fd));
1286 }
1287
TEST_F(protocol,tcp_fastopen)1288 TEST_F(protocol, tcp_fastopen)
1289 {
1290 const bool restricted = variant->sandbox == TCP_SANDBOX &&
1291 variant->prot.type == SOCK_STREAM &&
1292 (variant->prot.protocol == IPPROTO_TCP ||
1293 variant->prot.protocol == IPPROTO_IP) &&
1294 (variant->prot.domain == AF_INET ||
1295 variant->prot.domain == AF_INET6);
1296 const struct landlock_ruleset_attr ruleset_attr = {
1297 .handled_access_net = LANDLOCK_ACCESS_NET_CONNECT_TCP,
1298 };
1299 int bind_fd, client_fd, status;
1300 char buf;
1301 pid_t child;
1302
1303 bind_fd = socket_variant(&self->srv0);
1304 ASSERT_LE(0, bind_fd);
1305 EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0));
1306 if (self->srv0.protocol.type == SOCK_STREAM)
1307 EXPECT_EQ(0, listen(bind_fd, backlog));
1308
1309 child = fork();
1310 ASSERT_LE(0, child);
1311 if (child == 0) {
1312 int connect_fd, ret;
1313
1314 /* Closes listening socket for the child. */
1315 EXPECT_EQ(0, close(bind_fd));
1316
1317 connect_fd = socket_variant(&self->srv0);
1318 ASSERT_LE(0, connect_fd);
1319
1320 if (variant->sandbox == TCP_SANDBOX) {
1321 const int ruleset_fd = landlock_create_ruleset(
1322 &ruleset_attr, sizeof(ruleset_attr), 0);
1323 ASSERT_LE(0, ruleset_fd);
1324
1325 enforce_ruleset(_metadata, ruleset_fd);
1326 EXPECT_EQ(0, close(ruleset_fd));
1327 }
1328
1329 /* Fast Open with no address. */
1330 ret = sendto_variant(connect_fd, NULL, NULL, 0, MSG_FASTOPEN);
1331 if (self->srv0.protocol.domain == AF_UNIX) {
1332 EXPECT_EQ(-ENOTCONN, ret);
1333 } else if (self->srv0.protocol.type == SOCK_DGRAM) {
1334 EXPECT_EQ(-EDESTADDRREQ, ret);
1335 } else {
1336 EXPECT_EQ(-EINVAL, ret);
1337 }
1338
1339 /* Fast Open to a denied address. */
1340 ret = sendto_variant(connect_fd, &self->srv0, "A", 1,
1341 MSG_FASTOPEN);
1342 if (restricted) {
1343 EXPECT_EQ(-EACCES, ret);
1344 } else if (self->srv0.protocol.domain == AF_UNIX &&
1345 self->srv0.protocol.type == SOCK_STREAM) {
1346 EXPECT_EQ(-EOPNOTSUPP, ret);
1347 } else {
1348 EXPECT_EQ(0, ret);
1349 }
1350
1351 EXPECT_EQ(0, close(connect_fd));
1352 _exit(_metadata->exit_code);
1353 return;
1354 }
1355
1356 client_fd = bind_fd;
1357 if (!restricted && self->srv0.protocol.type == SOCK_STREAM &&
1358 self->srv0.protocol.domain != AF_UNIX) {
1359 client_fd = accept(bind_fd, NULL, 0);
1360 ASSERT_LE(0, client_fd);
1361 }
1362
1363 if (restricted) {
1364 EXPECT_EQ(-1, read(client_fd, &buf, 1));
1365 EXPECT_EQ(ENOTCONN, errno);
1366 } else if (self->srv0.protocol.domain == AF_UNIX &&
1367 self->srv0.protocol.type == SOCK_STREAM) {
1368 EXPECT_EQ(-1, read(client_fd, &buf, 1));
1369 EXPECT_EQ(EINVAL, errno);
1370 } else {
1371 EXPECT_EQ(1, read(client_fd, &buf, 1));
1372 EXPECT_EQ('A', buf);
1373 }
1374
1375 EXPECT_EQ(child, waitpid(child, &status, 0));
1376 EXPECT_EQ(1, WIFEXITED(status));
1377 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1378
1379 if (client_fd != bind_fd)
1380 EXPECT_LE(0, close(client_fd));
1381
1382 EXPECT_EQ(0, close(bind_fd));
1383 }
1384
TEST_F(protocol,sendmsg_stream)1385 TEST_F(protocol, sendmsg_stream)
1386 {
1387 int srv0_fd, tmp_fd, client_fd, res;
1388 char read_buf[1] = { 0 };
1389
1390 /*
1391 * Simple test for stream sockets: just deny all connect()/
1392 * send(explicit addr)/bind(), and make sure we don't interfere with any
1393 * operation.
1394 */
1395 if (variant->prot.type != SOCK_STREAM)
1396 return;
1397
1398 if (variant->sandbox == UDP_SANDBOX) {
1399 const struct landlock_ruleset_attr ruleset_attr = {
1400 .handled_access_net =
1401 LANDLOCK_ACCESS_NET_BIND_UDP |
1402 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1403 };
1404 const int ruleset_fd = landlock_create_ruleset(
1405 &ruleset_attr, sizeof(ruleset_attr), 0);
1406 ASSERT_LE(0, ruleset_fd);
1407 enforce_ruleset(_metadata, ruleset_fd);
1408 EXPECT_EQ(0, close(ruleset_fd));
1409 }
1410
1411 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1412 ASSERT_LE(0, srv0_fd = socket_variant(&self->srv0));
1413 ASSERT_EQ(0, bind_variant(srv0_fd, &self->srv0));
1414 ASSERT_EQ(0, listen(srv0_fd, backlog));
1415
1416 /* Send on a non-connected socket. */
1417 res = sendto_variant(client_fd, NULL, "A", 1, 0);
1418 if (variant->prot.domain == AF_UNIX) {
1419 EXPECT_EQ(-ENOTCONN, res);
1420 } else {
1421 EXPECT_EQ(-EPIPE, res);
1422 }
1423
1424 /* Send to a truncated (invalid) address on a non-connected socket. */
1425 res = sendto_variant_addrlen(client_fd, &self->srv0,
1426 get_addrlen(&self->srv0, true) - 1, "B", 1,
1427 0);
1428 if (variant->prot.domain == AF_UNIX) {
1429 EXPECT_EQ(-EOPNOTSUPP, res);
1430 } else {
1431 EXPECT_EQ(-EPIPE, res);
1432 }
1433
1434 /* Connect. */
1435 ASSERT_EQ(0, connect_variant(client_fd, &self->srv0));
1436 tmp_fd = accept(srv0_fd, NULL, 0);
1437 ASSERT_LE(0, tmp_fd);
1438 EXPECT_EQ(0, close(srv0_fd));
1439 srv0_fd = tmp_fd;
1440
1441 /* Send without an explicit address. */
1442 EXPECT_EQ(0, sendto_variant(client_fd, NULL, "C", 1, 0));
1443 EXPECT_EQ(1, recv(srv0_fd, read_buf, 1, 0))
1444 {
1445 TH_LOG("recv() failed: %s", strerror(errno));
1446 }
1447 EXPECT_EQ(read_buf[0], 'C');
1448
1449 /* Send to a truncated (invalid) address. */
1450 res = sendto_variant_addrlen(client_fd, &self->srv0,
1451 get_addrlen(&self->srv0, true) - 1, "D", 1,
1452 0);
1453 if (variant->prot.domain == AF_UNIX) {
1454 EXPECT_EQ(-EISCONN, res);
1455 } else {
1456 ASSERT_EQ(0, res);
1457 EXPECT_EQ(1, recv(srv0_fd, read_buf, 1, 0))
1458 {
1459 TH_LOG("recv() failed: %s", strerror(errno));
1460 }
1461 EXPECT_EQ(read_buf[0], 'D');
1462 }
1463
1464 /* Send to a valid but different address. */
1465 res = sendto_variant(client_fd, &self->srv1, "E", 1, 0);
1466 if (variant->prot.domain == AF_UNIX) {
1467 EXPECT_EQ(-EISCONN, res);
1468 } else {
1469 ASSERT_EQ(0, res);
1470 EXPECT_EQ(1, recv(srv0_fd, read_buf, 1, 0))
1471 {
1472 TH_LOG("recv() failed: %s", strerror(errno));
1473 }
1474 EXPECT_EQ(read_buf[0], 'E');
1475 }
1476
1477 EXPECT_EQ(0, close(client_fd));
1478 }
1479
TEST_F(protocol,sendmsg_dgram)1480 TEST_F(protocol, sendmsg_dgram)
1481 {
1482 const bool restricted = is_restricted(&variant->prot, variant->sandbox);
1483 int srv0_fd, srv1_fd, client_fd, child, status, res;
1484
1485 if (variant->prot.type != SOCK_DGRAM)
1486 return;
1487
1488 /* Prepare server on port #0 to be allowed. */
1489 ASSERT_LE(0, srv0_fd = socket_variant(&self->srv0));
1490 ASSERT_EQ(0, bind_variant(srv0_fd, &self->srv0));
1491
1492 /* And another server on port #1 to be denied. */
1493 ASSERT_LE(0, srv1_fd = socket_variant(&self->srv1));
1494 ASSERT_EQ(0, bind_variant(srv1_fd, &self->srv1));
1495
1496 /*
1497 * Check that sockets connected before restrictions are not impacted in
1498 * any way.
1499 */
1500 child = fork();
1501 ASSERT_LE(0, child);
1502 if (child == 0) {
1503 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1504 ASSERT_EQ(0, connect_variant(client_fd, &self->srv0));
1505 if (variant->sandbox == UDP_SANDBOX) {
1506 /* Deny all connect()/send(explicit addr)/bind(). */
1507 const struct landlock_ruleset_attr ruleset_attr = {
1508 .handled_access_net =
1509 LANDLOCK_ACCESS_NET_BIND_UDP |
1510 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1511 };
1512 const int ruleset_fd = landlock_create_ruleset(
1513 &ruleset_attr, sizeof(ruleset_attr), 0);
1514 ASSERT_LE(0, ruleset_fd);
1515 enforce_ruleset(_metadata, ruleset_fd);
1516 EXPECT_EQ(0, close(ruleset_fd));
1517 }
1518 EXPECT_EQ(0,
1519 test_sendmsg(_metadata, &variant->prot, client_fd,
1520 srv0_fd, NULL, restricted, restricted));
1521 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1522 srv0_fd, &self->srv0, restricted,
1523 restricted));
1524 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1525 srv1_fd, &self->srv1, restricted,
1526 restricted));
1527 EXPECT_EQ(0, close(client_fd));
1528 _exit(_metadata->exit_code);
1529 }
1530 EXPECT_EQ(child, waitpid(child, &status, 0));
1531 EXPECT_EQ(1, WIFEXITED(status));
1532 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1533
1534 /*
1535 * Restrict connect/send, but not bind(). Then try sending with no
1536 * destination (and no remote peer set), an allowed destination, then a
1537 * denied destination.
1538 */
1539 child = fork();
1540 ASSERT_LE(0, child);
1541 if (child == 0) {
1542 if (variant->sandbox == UDP_SANDBOX) {
1543 const struct landlock_ruleset_attr ruleset_attr = {
1544 .handled_access_net =
1545 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1546 };
1547 const struct landlock_net_port_attr send_p0 = {
1548 .allowed_access =
1549 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1550 .port = self->srv0.port,
1551 };
1552 const int ruleset_fd = landlock_create_ruleset(
1553 &ruleset_attr, sizeof(ruleset_attr), 0);
1554 ASSERT_LE(0, ruleset_fd);
1555 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
1556 LANDLOCK_RULE_NET_PORT,
1557 &send_p0, 0));
1558 enforce_ruleset(_metadata, ruleset_fd);
1559 EXPECT_EQ(0, close(ruleset_fd));
1560 }
1561 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1562 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1563 -1, NULL, false, false));
1564 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1565 srv0_fd, &self->srv0, false, false));
1566 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1567 srv1_fd, &self->srv1, false,
1568 restricted));
1569 EXPECT_EQ(0, close(client_fd));
1570 _exit(_metadata->exit_code);
1571 return;
1572 }
1573 EXPECT_EQ(child, waitpid(child, &status, 0));
1574 EXPECT_EQ(1, WIFEXITED(status));
1575 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1576
1577 /*
1578 * Rest of this test is just for autobind enforcement, which only exists
1579 * in IP sockets.
1580 */
1581 if (variant->prot.domain != AF_INET && variant->prot.domain != AF_INET6)
1582 return;
1583
1584 /* Restrict bind() to explicit calls with an arbitrary (non-0) port. */
1585 child = fork();
1586 ASSERT_LE(0, child);
1587 if (child == 0) {
1588 const uint16_t allowed_src_port = 42424;
1589 struct service_fixture allowed_src;
1590
1591 allowed_src = self->srv0;
1592 set_port(&allowed_src, allowed_src_port);
1593 if (variant->sandbox == UDP_SANDBOX) {
1594 const struct landlock_ruleset_attr ruleset_attr = {
1595 .handled_access_net =
1596 LANDLOCK_ACCESS_NET_BIND_UDP,
1597 };
1598 const struct landlock_net_port_attr rule = {
1599 .allowed_access = LANDLOCK_ACCESS_NET_BIND_UDP,
1600 .port = allowed_src_port,
1601 };
1602 const int ruleset_fd = landlock_create_ruleset(
1603 &ruleset_attr, sizeof(ruleset_attr), 0);
1604 ASSERT_LE(0, ruleset_fd);
1605 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
1606 LANDLOCK_RULE_NET_PORT,
1607 &rule, 0));
1608 enforce_ruleset(_metadata, ruleset_fd);
1609 EXPECT_EQ(0, close(ruleset_fd));
1610 }
1611 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1612
1613 /* Check that implicit bind(0) in sendmsg() is denied. */
1614 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1615 srv0_fd, &self->srv0, restricted,
1616 false));
1617
1618 /* Same thing for autobind in connect(). */
1619 res = connect_variant(client_fd, &self->srv0);
1620 if (restricted) {
1621 EXPECT_EQ(-EACCES, res);
1622 } else {
1623 EXPECT_EQ(0, res);
1624 }
1625 EXPECT_EQ(0, close(client_fd));
1626
1627 /* Make sendmsg() work by explicitly binding to the only allowed port. */
1628 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1629 EXPECT_EQ(0, bind_variant(client_fd, &allowed_src));
1630 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1631 srv0_fd, &self->srv0, restricted,
1632 false));
1633 EXPECT_EQ(0, close(client_fd));
1634
1635 /* Make connect() work by explicitly binding to the only allowed port. */
1636 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1637 EXPECT_EQ(0, bind_variant(client_fd, &allowed_src));
1638 EXPECT_EQ(0, connect_variant(client_fd, &self->srv0));
1639 EXPECT_EQ(0, close(client_fd));
1640
1641 _exit(_metadata->exit_code);
1642 return;
1643 }
1644 EXPECT_EQ(child, waitpid(child, &status, 0));
1645 EXPECT_EQ(1, WIFEXITED(status));
1646 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1647
1648 /*
1649 * Check that %LANDLOCK_ACCESS_NET_BIND_UDP on port 0 allows implicit
1650 * autobinds.
1651 */
1652 child = fork();
1653 ASSERT_LE(0, child);
1654 if (child == 0) {
1655 if (variant->sandbox == UDP_SANDBOX) {
1656 const struct landlock_ruleset_attr ruleset_attr = {
1657 .handled_access_net =
1658 LANDLOCK_ACCESS_NET_BIND_UDP,
1659 };
1660 const struct landlock_net_port_attr rule = {
1661 .allowed_access = LANDLOCK_ACCESS_NET_BIND_UDP,
1662 .port = 0,
1663 };
1664 const int ruleset_fd = landlock_create_ruleset(
1665 &ruleset_attr, sizeof(ruleset_attr), 0);
1666 ASSERT_LE(0, ruleset_fd);
1667 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
1668 LANDLOCK_RULE_NET_PORT,
1669 &rule, 0));
1670 enforce_ruleset(_metadata, ruleset_fd);
1671 EXPECT_EQ(0, close(ruleset_fd));
1672 }
1673 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1674 EXPECT_EQ(0, test_sendmsg(_metadata, &variant->prot, client_fd,
1675 srv0_fd, &self->srv0, false, false));
1676 EXPECT_EQ(0, close(client_fd));
1677 _exit(_metadata->exit_code);
1678 }
1679 EXPECT_EQ(child, waitpid(child, &status, 0));
1680 EXPECT_EQ(1, WIFEXITED(status));
1681 EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
1682 }
1683
TEST_F(protocol,sendmsg_unspec)1684 TEST_F(protocol, sendmsg_unspec)
1685 {
1686 const bool restricted = is_restricted(&variant->prot, variant->sandbox);
1687 int client_fd, srv0_fd, srv1_fd, res;
1688 char read_buf[1] = { 0 };
1689
1690 /*
1691 * We already test for the absence of influence on sendmsg for other
1692 * socket types and other address families, there's no point in adapting
1693 * this test for stream sockets too.
1694 */
1695 if (variant->prot.type != SOCK_DGRAM)
1696 return;
1697
1698 /* Prepare client of the right family. */
1699 ASSERT_LE(0, client_fd = socket_variant(&self->srv0));
1700
1701 /* Prepare server on port #0 to be allowed. */
1702 ASSERT_LE(0, srv0_fd = socket_variant(&self->srv0));
1703 ASSERT_EQ(0, bind_variant(srv0_fd, &self->srv0));
1704
1705 /* And another server on port #1 to be denied. */
1706 ASSERT_LE(0, srv1_fd = socket_variant(&self->srv1));
1707 ASSERT_EQ(0, bind_variant(srv1_fd, &self->srv1));
1708
1709 if (variant->sandbox == UDP_SANDBOX) {
1710 const struct landlock_ruleset_attr ruleset_attr = {
1711 .handled_access_net =
1712 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1713 };
1714 const struct landlock_net_port_attr rule = {
1715 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
1716 .port = self->srv0.port,
1717 };
1718 const int ruleset_fd = landlock_create_ruleset(
1719 &ruleset_attr, sizeof(ruleset_attr), 0);
1720 ASSERT_LE(0, ruleset_fd);
1721 ASSERT_EQ(0,
1722 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
1723 &rule, 0));
1724 enforce_ruleset(_metadata, ruleset_fd);
1725 EXPECT_EQ(0, close(ruleset_fd));
1726 }
1727
1728 /* Explicit AF_UNSPEC address but truncated. */
1729 EXPECT_EQ(-EINVAL, sendto_variant_addrlen(
1730 client_fd, &self->unspec_srv0,
1731 get_addrlen(&self->unspec_srv0, true) - 1,
1732 "A", 1, 0));
1733
1734 /*
1735 * Explicit AF_UNSPEC address, should be treated as AF_INET by IPv4
1736 * sockets (and thus map to srv0, allowed), but be denied by IPv6
1737 * sockets.
1738 */
1739 res = sendto_variant(client_fd, &self->unspec_srv0, "B", 1, 0);
1740 if (variant->prot.domain == AF_INET6) {
1741 if (restricted) {
1742 /* Always denied on IPv6 socket. */
1743 EXPECT_EQ(-EACCES, res);
1744 } else {
1745 /* IPv6 sockets treat AF_UNSPEC as a NULL address. */
1746 EXPECT_EQ(-EDESTADDRREQ, res);
1747 }
1748 } else if (variant->prot.domain == AF_INET) {
1749 ASSERT_EQ(0, res);
1750 EXPECT_EQ(1, read(srv0_fd, read_buf, 1))
1751 {
1752 TH_LOG("read() failed: %s", strerror(errno));
1753 }
1754 EXPECT_EQ(read_buf[0], 'B');
1755 } else {
1756 /* Unix sockets don't accept AF_UNSPEC. */
1757 EXPECT_EQ(-EINVAL, res);
1758 }
1759
1760 /*
1761 * Explicit AF_UNSPEC address, should be treated as AF_INET on IPv4
1762 * sockets (and thus map to srv1, denied), and be denied on IPv6 sockets
1763 * as always.
1764 */
1765 res = sendto_variant(client_fd, &self->unspec_srv1, "C", 1, 0);
1766 if (variant->prot.domain == AF_INET6) {
1767 if (restricted) {
1768 /* Always denied on IPv6 socket. */
1769 EXPECT_EQ(-EACCES, res);
1770 } else {
1771 /* IPv6 sockets treat AF_UNSPEC as a NULL address. */
1772 EXPECT_EQ(-EDESTADDRREQ, res);
1773 }
1774 } else if (variant->prot.domain == AF_INET) {
1775 if (restricted) {
1776 /* Sending to srv1 is not allowed, only srv0. */
1777 EXPECT_EQ(-EACCES, res);
1778 } else {
1779 ASSERT_EQ(0, res);
1780 EXPECT_EQ(1, read(srv1_fd, read_buf, 1))
1781 {
1782 TH_LOG("read() failed: %s", strerror(errno));
1783 }
1784 EXPECT_EQ(read_buf[0], 'C');
1785 }
1786 } else {
1787 /* Unix sockets don't accept AF_UNSPEC. */
1788 EXPECT_EQ(-EINVAL, res);
1789 }
1790
1791 ASSERT_EQ(0, connect_variant(client_fd, &self->srv0));
1792
1793 /* Minimal explicit AF_UNSPEC address (just the sa_family_t field) */
1794 res = sendto_variant_addrlen(client_fd, &self->unspec_srv0,
1795 get_addrlen(&self->unspec_srv0, true), "D",
1796 1, 0);
1797 if (variant->prot.domain == AF_INET6) {
1798 if (restricted) {
1799 /* AF_UNSPEC is always denied in IPv6. */
1800 EXPECT_EQ(-EACCES, res);
1801 } else {
1802 /*
1803 * IPv6 sockets treat AF_UNSPEC as a NULL address,
1804 * falling back to the connected address.
1805 */
1806 ASSERT_EQ(0, res);
1807 EXPECT_EQ(1, read(srv0_fd, read_buf, 1));
1808 EXPECT_EQ(read_buf[0], 'D');
1809 }
1810 } else {
1811 /*
1812 * IPv4 socket will expect a struct sockaddr_in, our address is
1813 * considered truncated. And Unix sockets don't accept
1814 * AF_UNSPEC at all.
1815 */
1816 EXPECT_EQ(-EINVAL, res);
1817 }
1818 }
1819
FIXTURE(ipv4)1820 FIXTURE(ipv4)
1821 {
1822 struct service_fixture srv0, srv1;
1823 };
1824
FIXTURE_VARIANT(ipv4)1825 FIXTURE_VARIANT(ipv4)
1826 {
1827 const enum sandbox_type sandbox;
1828 const int type;
1829 };
1830
1831 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,no_sandbox_with_tcp)1832 FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_tcp) {
1833 /* clang-format on */
1834 .sandbox = NO_SANDBOX,
1835 .type = SOCK_STREAM,
1836 };
1837
1838 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,tcp_sandbox_with_tcp)1839 FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_tcp) {
1840 /* clang-format on */
1841 .sandbox = TCP_SANDBOX,
1842 .type = SOCK_STREAM,
1843 };
1844
1845 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,udp_sandbox_with_tcp)1846 FIXTURE_VARIANT_ADD(ipv4, udp_sandbox_with_tcp) {
1847 /* clang-format on */
1848 .sandbox = UDP_SANDBOX,
1849 .type = SOCK_STREAM,
1850 };
1851
1852 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,no_sandbox_with_udp)1853 FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_udp) {
1854 /* clang-format on */
1855 .sandbox = NO_SANDBOX,
1856 .type = SOCK_DGRAM,
1857 };
1858
1859 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,tcp_sandbox_with_udp)1860 FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_udp) {
1861 /* clang-format on */
1862 .sandbox = TCP_SANDBOX,
1863 .type = SOCK_DGRAM,
1864 };
1865
1866 /* clang-format off */
FIXTURE_VARIANT_ADD(ipv4,udp_sandbox_with_udp)1867 FIXTURE_VARIANT_ADD(ipv4, udp_sandbox_with_udp) {
1868 /* clang-format on */
1869 .sandbox = UDP_SANDBOX,
1870 .type = SOCK_DGRAM,
1871 };
1872
FIXTURE_SETUP(ipv4)1873 FIXTURE_SETUP(ipv4)
1874 {
1875 const struct protocol_variant prot = {
1876 .domain = AF_INET,
1877 .type = variant->type,
1878 };
1879
1880 disable_caps(_metadata);
1881
1882 set_service(&self->srv0, prot, 0);
1883 set_service(&self->srv1, prot, 1);
1884
1885 setup_loopback(_metadata);
1886 };
1887
FIXTURE_TEARDOWN(ipv4)1888 FIXTURE_TEARDOWN(ipv4)
1889 {
1890 }
1891
TEST_F(ipv4,from_unix_to_inet)1892 TEST_F(ipv4, from_unix_to_inet)
1893 {
1894 int unix_stream_fd, unix_dgram_fd;
1895
1896 if (variant->sandbox == TCP_SANDBOX ||
1897 variant->sandbox == UDP_SANDBOX) {
1898 const __u64 access_rights =
1899 (variant->sandbox == TCP_SANDBOX ?
1900 LANDLOCK_ACCESS_NET_BIND_TCP |
1901 LANDLOCK_ACCESS_NET_CONNECT_TCP :
1902 LANDLOCK_ACCESS_NET_BIND_UDP |
1903 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
1904 const struct landlock_ruleset_attr ruleset_attr = {
1905 .handled_access_net = access_rights,
1906 };
1907 const struct landlock_net_port_attr tcp_bind_connect_p0 = {
1908 .allowed_access = access_rights,
1909 .port = self->srv0.port,
1910 };
1911 int ruleset_fd;
1912
1913 /* Denies connect and bind to check errno value. */
1914 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
1915 sizeof(ruleset_attr), 0);
1916 ASSERT_LE(0, ruleset_fd);
1917
1918 /* Allows connect and bind for srv0. */
1919 ASSERT_EQ(0,
1920 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
1921 &tcp_bind_connect_p0, 0));
1922
1923 enforce_ruleset(_metadata, ruleset_fd);
1924 EXPECT_EQ(0, close(ruleset_fd));
1925 }
1926
1927 unix_stream_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
1928 ASSERT_LE(0, unix_stream_fd);
1929
1930 unix_dgram_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1931 ASSERT_LE(0, unix_dgram_fd);
1932
1933 /* Checks unix stream bind and connect for srv0. */
1934 EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv0));
1935 EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv0));
1936
1937 /* Checks unix stream bind and connect for srv1. */
1938 EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv1))
1939 {
1940 TH_LOG("Wrong bind error: %s", strerror(errno));
1941 }
1942 EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv1));
1943
1944 /* Checks unix datagram bind and connect for srv0. */
1945 EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv0));
1946 EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv0));
1947
1948 /* Checks unix datagram bind and connect for srv1. */
1949 EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv1));
1950 EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv1));
1951 }
1952
FIXTURE(tcp_layers)1953 FIXTURE(tcp_layers)
1954 {
1955 struct service_fixture srv0, srv1;
1956 };
1957
FIXTURE_VARIANT(tcp_layers)1958 FIXTURE_VARIANT(tcp_layers)
1959 {
1960 const size_t num_layers;
1961 const int domain;
1962 };
1963
FIXTURE_SETUP(tcp_layers)1964 FIXTURE_SETUP(tcp_layers)
1965 {
1966 const struct protocol_variant prot = {
1967 .domain = variant->domain,
1968 .type = SOCK_STREAM,
1969 };
1970
1971 disable_caps(_metadata);
1972
1973 ASSERT_EQ(0, set_service(&self->srv0, prot, 0));
1974 ASSERT_EQ(0, set_service(&self->srv1, prot, 1));
1975
1976 setup_loopback(_metadata);
1977 };
1978
FIXTURE_TEARDOWN(tcp_layers)1979 FIXTURE_TEARDOWN(tcp_layers)
1980 {
1981 }
1982
1983 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,no_sandbox_with_ipv4)1984 FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv4) {
1985 /* clang-format on */
1986 .domain = AF_INET,
1987 .num_layers = 0,
1988 };
1989
1990 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,one_sandbox_with_ipv4)1991 FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv4) {
1992 /* clang-format on */
1993 .domain = AF_INET,
1994 .num_layers = 1,
1995 };
1996
1997 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,two_sandboxes_with_ipv4)1998 FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv4) {
1999 /* clang-format on */
2000 .domain = AF_INET,
2001 .num_layers = 2,
2002 };
2003
2004 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,three_sandboxes_with_ipv4)2005 FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv4) {
2006 /* clang-format on */
2007 .domain = AF_INET,
2008 .num_layers = 3,
2009 };
2010
2011 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,no_sandbox_with_ipv6)2012 FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv6) {
2013 /* clang-format on */
2014 .domain = AF_INET6,
2015 .num_layers = 0,
2016 };
2017
2018 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,one_sandbox_with_ipv6)2019 FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv6) {
2020 /* clang-format on */
2021 .domain = AF_INET6,
2022 .num_layers = 1,
2023 };
2024
2025 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,two_sandboxes_with_ipv6)2026 FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv6) {
2027 /* clang-format on */
2028 .domain = AF_INET6,
2029 .num_layers = 2,
2030 };
2031
2032 /* clang-format off */
FIXTURE_VARIANT_ADD(tcp_layers,three_sandboxes_with_ipv6)2033 FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv6) {
2034 /* clang-format on */
2035 .domain = AF_INET6,
2036 .num_layers = 3,
2037 };
2038
TEST_F(tcp_layers,ruleset_overlap)2039 TEST_F(tcp_layers, ruleset_overlap)
2040 {
2041 const struct landlock_ruleset_attr ruleset_attr = {
2042 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
2043 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2044 };
2045 const struct landlock_net_port_attr tcp_bind = {
2046 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2047 .port = self->srv0.port,
2048 };
2049 const struct landlock_net_port_attr tcp_bind_connect = {
2050 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP |
2051 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2052 .port = self->srv0.port,
2053 };
2054
2055 if (variant->num_layers >= 1) {
2056 int ruleset_fd;
2057
2058 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2059 sizeof(ruleset_attr), 0);
2060 ASSERT_LE(0, ruleset_fd);
2061
2062 /* Allows bind. */
2063 ASSERT_EQ(0,
2064 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2065 &tcp_bind, 0));
2066 /* Also allows bind, but allows connect too. */
2067 ASSERT_EQ(0,
2068 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2069 &tcp_bind_connect, 0));
2070 enforce_ruleset(_metadata, ruleset_fd);
2071 EXPECT_EQ(0, close(ruleset_fd));
2072 }
2073
2074 if (variant->num_layers >= 2) {
2075 int ruleset_fd;
2076
2077 /* Creates another ruleset layer. */
2078 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2079 sizeof(ruleset_attr), 0);
2080 ASSERT_LE(0, ruleset_fd);
2081
2082 /* Only allows bind. */
2083 ASSERT_EQ(0,
2084 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2085 &tcp_bind, 0));
2086 enforce_ruleset(_metadata, ruleset_fd);
2087 EXPECT_EQ(0, close(ruleset_fd));
2088 }
2089
2090 if (variant->num_layers >= 3) {
2091 int ruleset_fd;
2092
2093 /* Creates another ruleset layer. */
2094 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2095 sizeof(ruleset_attr), 0);
2096 ASSERT_LE(0, ruleset_fd);
2097
2098 /* Try to allow bind and connect. */
2099 ASSERT_EQ(0,
2100 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2101 &tcp_bind_connect, 0));
2102 enforce_ruleset(_metadata, ruleset_fd);
2103 EXPECT_EQ(0, close(ruleset_fd));
2104 }
2105
2106 /*
2107 * Forbids to connect to the socket because only one ruleset layer
2108 * allows connect.
2109 */
2110 test_bind_and_connect(_metadata, &self->srv0, false,
2111 variant->num_layers >= 2);
2112 }
2113
TEST_F(tcp_layers,ruleset_expand)2114 TEST_F(tcp_layers, ruleset_expand)
2115 {
2116 if (variant->num_layers >= 1) {
2117 const struct landlock_ruleset_attr ruleset_attr = {
2118 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
2119 };
2120 /* Allows bind for srv0. */
2121 const struct landlock_net_port_attr bind_srv0 = {
2122 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2123 .port = self->srv0.port,
2124 };
2125 int ruleset_fd;
2126
2127 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2128 sizeof(ruleset_attr), 0);
2129 ASSERT_LE(0, ruleset_fd);
2130 ASSERT_EQ(0,
2131 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2132 &bind_srv0, 0));
2133 enforce_ruleset(_metadata, ruleset_fd);
2134 EXPECT_EQ(0, close(ruleset_fd));
2135 }
2136
2137 if (variant->num_layers >= 2) {
2138 /* Expands network mask with connect action. */
2139 const struct landlock_ruleset_attr ruleset_attr = {
2140 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
2141 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2142 };
2143 /* Allows bind for srv0 and connect to srv0. */
2144 const struct landlock_net_port_attr tcp_bind_connect_p0 = {
2145 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP |
2146 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2147 .port = self->srv0.port,
2148 };
2149 /* Try to allow bind for srv1. */
2150 const struct landlock_net_port_attr tcp_bind_p1 = {
2151 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2152 .port = self->srv1.port,
2153 };
2154 int ruleset_fd;
2155
2156 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2157 sizeof(ruleset_attr), 0);
2158 ASSERT_LE(0, ruleset_fd);
2159 ASSERT_EQ(0,
2160 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2161 &tcp_bind_connect_p0, 0));
2162 ASSERT_EQ(0,
2163 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2164 &tcp_bind_p1, 0));
2165 enforce_ruleset(_metadata, ruleset_fd);
2166 EXPECT_EQ(0, close(ruleset_fd));
2167 }
2168
2169 if (variant->num_layers >= 3) {
2170 const struct landlock_ruleset_attr ruleset_attr = {
2171 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
2172 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2173 };
2174 /* Allows connect to srv0, without bind rule. */
2175 const struct landlock_net_port_attr tcp_bind_p0 = {
2176 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2177 .port = self->srv0.port,
2178 };
2179 int ruleset_fd;
2180
2181 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2182 sizeof(ruleset_attr), 0);
2183 ASSERT_LE(0, ruleset_fd);
2184 ASSERT_EQ(0,
2185 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2186 &tcp_bind_p0, 0));
2187 enforce_ruleset(_metadata, ruleset_fd);
2188 EXPECT_EQ(0, close(ruleset_fd));
2189 }
2190
2191 test_bind_and_connect(_metadata, &self->srv0, false,
2192 variant->num_layers >= 3);
2193
2194 test_bind_and_connect(_metadata, &self->srv1, variant->num_layers >= 1,
2195 variant->num_layers >= 2);
2196 }
2197
2198 /* clang-format off */
FIXTURE(mini)2199 FIXTURE(mini) {};
2200 /* clang-format on */
2201
FIXTURE_SETUP(mini)2202 FIXTURE_SETUP(mini)
2203 {
2204 disable_caps(_metadata);
2205
2206 setup_loopback(_metadata);
2207 };
2208
FIXTURE_TEARDOWN(mini)2209 FIXTURE_TEARDOWN(mini)
2210 {
2211 }
2212
2213 /* clang-format off */
2214
2215 #define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP
2216
2217 #define ACCESS_ALL ( \
2218 LANDLOCK_ACCESS_NET_BIND_TCP | \
2219 LANDLOCK_ACCESS_NET_CONNECT_TCP | \
2220 LANDLOCK_ACCESS_NET_BIND_UDP | \
2221 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP)
2222
2223 /* clang-format on */
2224
TEST_F(mini,network_access_rights)2225 TEST_F(mini, network_access_rights)
2226 {
2227 const struct landlock_ruleset_attr ruleset_attr = {
2228 .handled_access_net = ACCESS_ALL,
2229 };
2230 struct landlock_net_port_attr net_port = {
2231 .port = sock_port_start,
2232 };
2233 int ruleset_fd;
2234 __u64 access;
2235
2236 ruleset_fd =
2237 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2238 ASSERT_LE(0, ruleset_fd);
2239
2240 for (access = 1; access <= ACCESS_LAST; access <<= 1) {
2241 net_port.allowed_access = access;
2242 EXPECT_EQ(0,
2243 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2244 &net_port, 0))
2245 {
2246 TH_LOG("Failed to add rule with access 0x%llx: %s",
2247 (unsigned long long)access, strerror(errno));
2248 }
2249 }
2250 EXPECT_EQ(0, close(ruleset_fd));
2251 }
2252
2253 /* Checks invalid attribute, out of landlock network access range. */
TEST_F(mini,ruleset_with_unknown_access)2254 TEST_F(mini, ruleset_with_unknown_access)
2255 {
2256 __u64 access_mask;
2257
2258 for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
2259 access_mask >>= 1) {
2260 const struct landlock_ruleset_attr ruleset_attr = {
2261 .handled_access_net = access_mask,
2262 };
2263
2264 EXPECT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
2265 sizeof(ruleset_attr), 0));
2266 EXPECT_EQ(EINVAL, errno);
2267 }
2268 }
2269
TEST_F(mini,rule_with_unknown_access)2270 TEST_F(mini, rule_with_unknown_access)
2271 {
2272 const struct landlock_ruleset_attr ruleset_attr = {
2273 .handled_access_net = ACCESS_ALL,
2274 };
2275 struct landlock_net_port_attr net_port = {
2276 .port = sock_port_start,
2277 };
2278 int ruleset_fd;
2279 __u64 access;
2280
2281 ruleset_fd =
2282 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2283 ASSERT_LE(0, ruleset_fd);
2284
2285 for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) {
2286 net_port.allowed_access = access;
2287 EXPECT_EQ(-1,
2288 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2289 &net_port, 0));
2290 EXPECT_EQ(EINVAL, errno);
2291 }
2292 EXPECT_EQ(0, close(ruleset_fd));
2293 }
2294
TEST_F(mini,rule_with_unhandled_access)2295 TEST_F(mini, rule_with_unhandled_access)
2296 {
2297 struct landlock_ruleset_attr ruleset_attr = {
2298 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
2299 };
2300 struct landlock_net_port_attr net_port = {
2301 .port = sock_port_start,
2302 };
2303 int ruleset_fd;
2304 __u64 access;
2305
2306 ruleset_fd =
2307 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2308 ASSERT_LE(0, ruleset_fd);
2309
2310 for (access = 1; access > 0; access <<= 1) {
2311 int err;
2312
2313 net_port.allowed_access = access;
2314 err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2315 &net_port, 0);
2316 if (access == ruleset_attr.handled_access_net) {
2317 EXPECT_EQ(0, err);
2318 } else {
2319 EXPECT_EQ(-1, err);
2320 EXPECT_EQ(EINVAL, errno);
2321 }
2322 }
2323
2324 EXPECT_EQ(0, close(ruleset_fd));
2325 }
2326
TEST_F(mini,inval)2327 TEST_F(mini, inval)
2328 {
2329 const struct landlock_ruleset_attr ruleset_attr = {
2330 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP
2331 };
2332 const struct landlock_net_port_attr tcp_bind_connect = {
2333 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP |
2334 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2335 .port = sock_port_start,
2336 };
2337 const struct landlock_net_port_attr tcp_denied = {
2338 .allowed_access = 0,
2339 .port = sock_port_start,
2340 };
2341 const struct landlock_net_port_attr tcp_bind = {
2342 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2343 .port = sock_port_start,
2344 };
2345 int ruleset_fd;
2346
2347 ruleset_fd =
2348 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2349 ASSERT_LE(0, ruleset_fd);
2350
2351 /* Checks unhandled allowed_access. */
2352 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2353 &tcp_bind_connect, 0));
2354 EXPECT_EQ(EINVAL, errno);
2355
2356 /* Checks zero access value. */
2357 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2358 &tcp_denied, 0));
2359 EXPECT_EQ(ENOMSG, errno);
2360
2361 /* Adds with legitimate values. */
2362 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2363 &tcp_bind, 0));
2364 }
2365
TEST_F(mini,tcp_port_overflow)2366 TEST_F(mini, tcp_port_overflow)
2367 {
2368 const struct landlock_ruleset_attr ruleset_attr = {
2369 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
2370 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2371 };
2372 const struct landlock_net_port_attr port_max_bind = {
2373 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2374 .port = UINT16_MAX,
2375 };
2376 const struct landlock_net_port_attr port_max_connect = {
2377 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP,
2378 .port = UINT16_MAX,
2379 };
2380 const struct landlock_net_port_attr port_overflow1 = {
2381 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2382 .port = UINT16_MAX + 1,
2383 };
2384 const struct landlock_net_port_attr port_overflow2 = {
2385 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2386 .port = UINT16_MAX + 2,
2387 };
2388 const struct landlock_net_port_attr port_overflow3 = {
2389 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2390 .port = UINT32_MAX + 1UL,
2391 };
2392 const struct landlock_net_port_attr port_overflow4 = {
2393 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2394 .port = UINT32_MAX + 2UL,
2395 };
2396 const struct protocol_variant ipv4_tcp = {
2397 .domain = AF_INET,
2398 .type = SOCK_STREAM,
2399 };
2400 struct service_fixture srv_denied, srv_max_allowed;
2401 int ruleset_fd;
2402
2403 ASSERT_EQ(0, set_service(&srv_denied, ipv4_tcp, 0));
2404
2405 /* Be careful to avoid port inconsistencies. */
2406 srv_max_allowed = srv_denied;
2407 srv_max_allowed.port = port_max_bind.port;
2408 srv_max_allowed.ipv4_addr.sin_port = htons(port_max_bind.port);
2409
2410 ruleset_fd =
2411 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2412 ASSERT_LE(0, ruleset_fd);
2413
2414 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2415 &port_max_bind, 0));
2416
2417 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2418 &port_overflow1, 0));
2419 EXPECT_EQ(EINVAL, errno);
2420
2421 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2422 &port_overflow2, 0));
2423 EXPECT_EQ(EINVAL, errno);
2424
2425 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2426 &port_overflow3, 0));
2427 EXPECT_EQ(EINVAL, errno);
2428
2429 /* Interleaves with invalid rule additions. */
2430 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2431 &port_max_connect, 0));
2432
2433 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2434 &port_overflow4, 0));
2435 EXPECT_EQ(EINVAL, errno);
2436
2437 enforce_ruleset(_metadata, ruleset_fd);
2438
2439 test_bind_and_connect(_metadata, &srv_denied, true, true);
2440 test_bind_and_connect(_metadata, &srv_max_allowed, false, false);
2441 }
2442
FIXTURE(ipv4_tcp)2443 FIXTURE(ipv4_tcp)
2444 {
2445 struct service_fixture srv0, srv1;
2446 };
2447
FIXTURE_SETUP(ipv4_tcp)2448 FIXTURE_SETUP(ipv4_tcp)
2449 {
2450 const struct protocol_variant ipv4_tcp = {
2451 .domain = AF_INET,
2452 .type = SOCK_STREAM,
2453 };
2454
2455 disable_caps(_metadata);
2456
2457 ASSERT_EQ(0, set_service(&self->srv0, ipv4_tcp, 0));
2458 ASSERT_EQ(0, set_service(&self->srv1, ipv4_tcp, 1));
2459
2460 setup_loopback(_metadata);
2461 };
2462
FIXTURE_TEARDOWN(ipv4_tcp)2463 FIXTURE_TEARDOWN(ipv4_tcp)
2464 {
2465 }
2466
TEST_F(ipv4_tcp,port_endianness)2467 TEST_F(ipv4_tcp, port_endianness)
2468 {
2469 const struct landlock_ruleset_attr ruleset_attr = {
2470 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
2471 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2472 };
2473 const struct landlock_net_port_attr bind_host_endian_p0 = {
2474 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2475 /* Host port format. */
2476 .port = self->srv0.port,
2477 };
2478 const struct landlock_net_port_attr connect_big_endian_p0 = {
2479 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP,
2480 /* Big endian port format. */
2481 .port = htons(self->srv0.port),
2482 };
2483 const struct landlock_net_port_attr bind_connect_host_endian_p1 = {
2484 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP |
2485 LANDLOCK_ACCESS_NET_CONNECT_TCP,
2486 /* Host port format. */
2487 .port = self->srv1.port,
2488 };
2489 const unsigned int one = 1;
2490 const char little_endian = *(const char *)&one;
2491 int ruleset_fd;
2492
2493 ruleset_fd =
2494 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2495 ASSERT_LE(0, ruleset_fd);
2496 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2497 &bind_host_endian_p0, 0));
2498 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2499 &connect_big_endian_p0, 0));
2500 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2501 &bind_connect_host_endian_p1, 0));
2502 enforce_ruleset(_metadata, ruleset_fd);
2503
2504 /* No restriction for big endinan CPU. */
2505 test_bind_and_connect(_metadata, &self->srv0, false, little_endian);
2506
2507 /* No restriction for any CPU. */
2508 test_bind_and_connect(_metadata, &self->srv1, false, false);
2509 }
2510
TEST_F(ipv4_tcp,with_fs)2511 TEST_F(ipv4_tcp, with_fs)
2512 {
2513 const struct landlock_ruleset_attr ruleset_attr_fs_net = {
2514 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,
2515 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
2516 };
2517 struct landlock_path_beneath_attr path_beneath = {
2518 .allowed_access = LANDLOCK_ACCESS_FS_READ_DIR,
2519 .parent_fd = -1,
2520 };
2521 struct landlock_net_port_attr tcp_bind = {
2522 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
2523 .port = self->srv0.port,
2524 };
2525 int ruleset_fd, bind_fd, dir_fd;
2526
2527 /* Creates ruleset both for filesystem and network access. */
2528 ruleset_fd = landlock_create_ruleset(&ruleset_attr_fs_net,
2529 sizeof(ruleset_attr_fs_net), 0);
2530 ASSERT_LE(0, ruleset_fd);
2531
2532 /* Adds a filesystem rule. */
2533 path_beneath.parent_fd = open("/dev", O_PATH | O_DIRECTORY | O_CLOEXEC);
2534 ASSERT_LE(0, path_beneath.parent_fd);
2535 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
2536 &path_beneath, 0));
2537 EXPECT_EQ(0, close(path_beneath.parent_fd));
2538
2539 /* Adds a network rule. */
2540 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2541 &tcp_bind, 0));
2542
2543 enforce_ruleset(_metadata, ruleset_fd);
2544 EXPECT_EQ(0, close(ruleset_fd));
2545
2546 /* Tests file access. */
2547 dir_fd = open("/dev", O_RDONLY);
2548 EXPECT_LE(0, dir_fd);
2549 EXPECT_EQ(0, close(dir_fd));
2550
2551 dir_fd = open("/", O_RDONLY);
2552 EXPECT_EQ(-1, dir_fd);
2553 EXPECT_EQ(EACCES, errno);
2554
2555 /* Tests port binding. */
2556 bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
2557 ASSERT_LE(0, bind_fd);
2558 EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0));
2559 EXPECT_EQ(0, close(bind_fd));
2560
2561 bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
2562 ASSERT_LE(0, bind_fd);
2563 EXPECT_EQ(-EACCES, bind_variant(bind_fd, &self->srv1));
2564 }
2565
FIXTURE(port_specific)2566 FIXTURE(port_specific)
2567 {
2568 struct service_fixture srv0;
2569 struct service_fixture cli1;
2570 };
2571
FIXTURE_VARIANT(port_specific)2572 FIXTURE_VARIANT(port_specific)
2573 {
2574 const enum sandbox_type sandbox;
2575 const struct protocol_variant prot;
2576 };
2577
2578 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,no_sandbox_with_ipv4)2579 FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv4) {
2580 /* clang-format on */
2581 .sandbox = NO_SANDBOX,
2582 .prot = {
2583 .domain = AF_INET,
2584 .type = SOCK_STREAM,
2585 },
2586 };
2587
2588 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,tcp_sandbox_with_ipv4)2589 FIXTURE_VARIANT_ADD(port_specific, tcp_sandbox_with_ipv4) {
2590 /* clang-format on */
2591 .sandbox = TCP_SANDBOX,
2592 .prot = {
2593 .domain = AF_INET,
2594 .type = SOCK_STREAM,
2595 },
2596 };
2597
2598 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,udp_sandbox_with_ipv4)2599 FIXTURE_VARIANT_ADD(port_specific, udp_sandbox_with_ipv4) {
2600 /* clang-format on */
2601 .sandbox = UDP_SANDBOX,
2602 .prot = {
2603 .domain = AF_INET,
2604 .type = SOCK_DGRAM,
2605 },
2606 };
2607
2608 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,no_sandbox_with_ipv6)2609 FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv6) {
2610 /* clang-format on */
2611 .sandbox = NO_SANDBOX,
2612 .prot = {
2613 .domain = AF_INET6,
2614 .type = SOCK_STREAM,
2615 },
2616 };
2617
2618 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,tcp_sandbox_with_ipv6)2619 FIXTURE_VARIANT_ADD(port_specific, tcp_sandbox_with_ipv6) {
2620 /* clang-format on */
2621 .sandbox = TCP_SANDBOX,
2622 .prot = {
2623 .domain = AF_INET6,
2624 .type = SOCK_STREAM,
2625 },
2626 };
2627
2628 /* clang-format off */
FIXTURE_VARIANT_ADD(port_specific,udp_sandbox_with_ipv6)2629 FIXTURE_VARIANT_ADD(port_specific, udp_sandbox_with_ipv6) {
2630 /* clang-format on */
2631 .sandbox = UDP_SANDBOX,
2632 .prot = {
2633 .domain = AF_INET6,
2634 .type = SOCK_DGRAM,
2635 },
2636 };
2637
FIXTURE_SETUP(port_specific)2638 FIXTURE_SETUP(port_specific)
2639 {
2640 disable_caps(_metadata);
2641
2642 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0));
2643 ASSERT_EQ(0, set_service(&self->cli1, variant->prot, 1));
2644
2645 setup_loopback(_metadata);
2646 };
2647
FIXTURE_TEARDOWN(port_specific)2648 FIXTURE_TEARDOWN(port_specific)
2649 {
2650 }
2651
TEST_F(port_specific,bind_connect_zero)2652 TEST_F(port_specific, bind_connect_zero)
2653 {
2654 int bind_fd, connect_fd, ret;
2655 uint16_t port;
2656
2657 /* Adds a rule layer with bind and connect actions. */
2658 if (variant->sandbox == TCP_SANDBOX ||
2659 variant->sandbox == UDP_SANDBOX) {
2660 const __u64 access_rights =
2661 (variant->sandbox == TCP_SANDBOX ?
2662 LANDLOCK_ACCESS_NET_BIND_TCP |
2663 LANDLOCK_ACCESS_NET_CONNECT_TCP :
2664 LANDLOCK_ACCESS_NET_BIND_UDP |
2665 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
2666 const struct landlock_ruleset_attr ruleset_attr = {
2667 .handled_access_net = access_rights,
2668 };
2669 const struct landlock_net_port_attr bind_connect_zero = {
2670 .allowed_access = access_rights,
2671 .port = 0,
2672 };
2673 int ruleset_fd;
2674
2675 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2676 sizeof(ruleset_attr), 0);
2677 ASSERT_LE(0, ruleset_fd);
2678
2679 /* Checks zero port value on bind and connect actions. */
2680 EXPECT_EQ(0,
2681 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2682 &bind_connect_zero, 0));
2683
2684 enforce_ruleset(_metadata, ruleset_fd);
2685 EXPECT_EQ(0, close(ruleset_fd));
2686 }
2687
2688 bind_fd = socket_variant(&self->srv0);
2689 ASSERT_LE(0, bind_fd);
2690
2691 connect_fd = socket_variant(&self->srv0);
2692 ASSERT_LE(0, connect_fd);
2693
2694 /* Sets address port to 0 for both protocol families. */
2695 set_port(&self->srv0, 0);
2696 /*
2697 * Binds on port 0, which selects a random port within
2698 * ip_local_port_range.
2699 */
2700 ret = bind_variant(bind_fd, &self->srv0);
2701 EXPECT_EQ(0, ret);
2702
2703 if (variant->prot.type == SOCK_STREAM)
2704 EXPECT_EQ(0, listen(bind_fd, backlog));
2705
2706 /* Connects on port 0. */
2707 ret = connect_variant(connect_fd, &self->srv0);
2708 if (variant->prot.type == SOCK_STREAM) {
2709 EXPECT_EQ(-ECONNREFUSED, ret);
2710 } else {
2711 EXPECT_EQ(0, ret);
2712 }
2713
2714 /* Sets binded port for both protocol families. */
2715 port = get_binded_port(bind_fd, &variant->prot);
2716 EXPECT_NE(0, port);
2717 set_port(&self->srv0, port);
2718 /* Connects on the binded port. */
2719 ret = connect_variant(connect_fd, &self->srv0);
2720 if (is_restricted(&variant->prot, variant->sandbox)) {
2721 /* Denied by Landlock. */
2722 EXPECT_EQ(-EACCES, ret);
2723 } else {
2724 EXPECT_EQ(0, ret);
2725 }
2726
2727 EXPECT_EQ(0, close(connect_fd));
2728 EXPECT_EQ(0, close(bind_fd));
2729 }
2730
TEST_F(port_specific,bind_connect_1023)2731 TEST_F(port_specific, bind_connect_1023)
2732 {
2733 int bind_fd, connect_fd, ret;
2734
2735 /* Adds a rule layer with bind and connect actions. */
2736 if (variant->sandbox == TCP_SANDBOX ||
2737 variant->sandbox == UDP_SANDBOX) {
2738 const __u64 bind_right = (variant->sandbox == TCP_SANDBOX ?
2739 LANDLOCK_ACCESS_NET_BIND_TCP :
2740 LANDLOCK_ACCESS_NET_BIND_UDP);
2741 const __u64 access_rights =
2742 (variant->sandbox == TCP_SANDBOX ?
2743 (LANDLOCK_ACCESS_NET_BIND_TCP |
2744 LANDLOCK_ACCESS_NET_CONNECT_TCP) :
2745 (LANDLOCK_ACCESS_NET_BIND_UDP |
2746 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP));
2747 const struct landlock_ruleset_attr ruleset_attr = {
2748 .handled_access_net = access_rights,
2749 };
2750 /* A rule with port value less than 1024. */
2751 const struct landlock_net_port_attr bind_connect_low_range = {
2752 .allowed_access = access_rights,
2753 .port = 1023,
2754 };
2755 /* A rule with 1024 port. */
2756 const struct landlock_net_port_attr bind_connect = {
2757 .allowed_access = access_rights,
2758 .port = 1024,
2759 };
2760 /* A rule with cli1's port, to use as source port. */
2761 const struct landlock_net_port_attr srcport = {
2762 .allowed_access = bind_right,
2763 .port = self->cli1.port,
2764 };
2765 int ruleset_fd;
2766
2767 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
2768 sizeof(ruleset_attr), 0);
2769 ASSERT_LE(0, ruleset_fd);
2770
2771 ASSERT_EQ(0,
2772 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2773 &bind_connect_low_range, 0));
2774 ASSERT_EQ(0,
2775 landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2776 &bind_connect, 0));
2777 if (variant->sandbox == UDP_SANDBOX) {
2778 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
2779 LANDLOCK_RULE_NET_PORT,
2780 &srcport, 0));
2781 }
2782
2783 enforce_ruleset(_metadata, ruleset_fd);
2784 EXPECT_EQ(0, close(ruleset_fd));
2785 }
2786
2787 bind_fd = socket_variant(&self->srv0);
2788 ASSERT_LE(0, bind_fd);
2789
2790 /* Sets address port to 1023 for both protocol families. */
2791 set_port(&self->srv0, 1023);
2792 /* Binds on port 1023. */
2793 ret = bind_variant(bind_fd, &self->srv0);
2794 /* Denied by the system. */
2795 EXPECT_EQ(-EACCES, ret);
2796
2797 /* Binds on port 1023. */
2798 set_cap(_metadata, CAP_NET_BIND_SERVICE);
2799 ret = bind_variant(bind_fd, &self->srv0);
2800 clear_cap(_metadata, CAP_NET_BIND_SERVICE);
2801 EXPECT_EQ(0, ret);
2802 if (variant->prot.type == SOCK_STREAM)
2803 EXPECT_EQ(0, listen(bind_fd, backlog));
2804
2805 connect_fd = socket_variant(&self->srv0);
2806 ASSERT_LE(0, connect_fd);
2807 if (variant->prot.type == SOCK_DGRAM) {
2808 /*
2809 * We are about to connect(), but bind() is restricted, so for
2810 * UDP sockets we need to use cli1's port as source port (the
2811 * only one we are allowed to use).
2812 */
2813 EXPECT_EQ(0, bind_variant(connect_fd, &self->cli1));
2814 }
2815 /* Connects on the binded port 1023. */
2816 ret = connect_variant(connect_fd, &self->srv0);
2817 EXPECT_EQ(0, ret);
2818
2819 EXPECT_EQ(0, close(connect_fd));
2820 EXPECT_EQ(0, close(bind_fd));
2821
2822 bind_fd = socket_variant(&self->srv0);
2823 ASSERT_LE(0, bind_fd);
2824
2825 connect_fd = socket_variant(&self->srv0);
2826 ASSERT_LE(0, connect_fd);
2827
2828 /* Sets address port to 1024 for both protocol families. */
2829 set_port(&self->srv0, 1024);
2830 /* Binds on port 1024. */
2831 ret = bind_variant(bind_fd, &self->srv0);
2832 EXPECT_EQ(0, ret);
2833 if (variant->prot.type == SOCK_STREAM)
2834 EXPECT_EQ(0, listen(bind_fd, backlog));
2835 if (variant->prot.type == SOCK_DGRAM)
2836 EXPECT_EQ(0, bind_variant(connect_fd, &self->cli1));
2837
2838 /* Connects on the binded port 1024. */
2839 ret = connect_variant(connect_fd, &self->srv0);
2840 EXPECT_EQ(0, ret);
2841
2842 EXPECT_EQ(0, close(connect_fd));
2843 EXPECT_EQ(0, close(bind_fd));
2844 }
2845
2846 /**
2847 * matches_auditlog - Check audit log for a network access denial
2848 *
2849 * @audit_fd: Audit file descriptor.
2850 * @blockers: A regex-escaped blocker string, e.g., "net\.bind_tcp".
2851 * @dir_addr: Either "saddr" or "daddr", ignored if addr is NULL.
2852 * @addr: A regex-escaped IP address string, or NULL.
2853 * @dir_port: Either "src" or "dest", ignored if addr is NULL.
2854 * @port: A port number, ignored if addr is NULL.
2855 */
matches_auditlog(const int audit_fd,const char * const blockers,const char * const dir_addr,const char * const addr,const char * const dir_port,const __u16 port)2856 static int matches_auditlog(const int audit_fd, const char *const blockers,
2857 const char *const dir_addr, const char *const addr,
2858 const char *const dir_port, const __u16 port)
2859 {
2860 static const char log_with_addrport_tmpl[] = REGEX_LANDLOCK_PREFIX
2861 " blockers=%s %s=%s %s=%u$";
2862 static const char log_without_addrport_tmpl[] = REGEX_LANDLOCK_PREFIX
2863 " blockers=%s";
2864 /*
2865 * Max strlen(blockers): 16
2866 * Max strlen(dir_addr): 5
2867 * Max strlen(addr): 12
2868 * Max strlen(dir_port): 4
2869 * Max strlen(%u port): 5
2870 */
2871 char log_match[sizeof(log_with_addrport_tmpl) + 42];
2872 int log_match_len;
2873
2874 if (addr == NULL)
2875 log_match_len = snprintf(log_match, sizeof(log_match),
2876 log_without_addrport_tmpl, blockers);
2877 else
2878 log_match_len = snprintf(log_match, sizeof(log_match),
2879 log_with_addrport_tmpl, blockers,
2880 dir_addr, addr, dir_port, port);
2881 if (log_match_len > sizeof(log_match))
2882 return -E2BIG;
2883
2884 return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
2885 NULL);
2886 }
2887
FIXTURE(audit)2888 FIXTURE(audit)
2889 {
2890 struct service_fixture srv0;
2891 struct service_fixture srv1;
2892 /* srv2 has a rule with no access but quiet bit set. */
2893 struct service_fixture srv2;
2894 struct service_fixture unspec_srv0;
2895 struct audit_filter audit_filter;
2896 int audit_fd;
2897 };
2898
FIXTURE_VARIANT(audit)2899 FIXTURE_VARIANT(audit)
2900 {
2901 const char *const addr;
2902 const struct protocol_variant prot;
2903 };
2904
2905 /* clang-format off */
FIXTURE_VARIANT_ADD(audit,ipv4_tcp)2906 FIXTURE_VARIANT_ADD(audit, ipv4_tcp) {
2907 /* clang-format on */
2908 .addr = "127\\.0\\.0\\.1",
2909 .prot = {
2910 .domain = AF_INET,
2911 .type = SOCK_STREAM,
2912 },
2913 };
2914
2915 /* clang-format off */
FIXTURE_VARIANT_ADD(audit,ipv4_udp)2916 FIXTURE_VARIANT_ADD(audit, ipv4_udp) {
2917 /* clang-format on */
2918 .addr = "127\\.0\\.0\\.1",
2919 .prot = {
2920 .domain = AF_INET,
2921 .type = SOCK_DGRAM,
2922 },
2923 };
2924
2925 /* clang-format off */
FIXTURE_VARIANT_ADD(audit,ipv6_tcp)2926 FIXTURE_VARIANT_ADD(audit, ipv6_tcp) {
2927 /* clang-format on */
2928 .addr = "::1",
2929 .prot = {
2930 .domain = AF_INET6,
2931 .type = SOCK_STREAM,
2932 },
2933 };
2934
2935 /* clang-format off */
FIXTURE_VARIANT_ADD(audit,ipv6_udp)2936 FIXTURE_VARIANT_ADD(audit, ipv6_udp) {
2937 /* clang-format on */
2938 .addr = "::1",
2939 .prot = {
2940 .domain = AF_INET6,
2941 .type = SOCK_DGRAM,
2942 },
2943 };
2944
FIXTURE_SETUP(audit)2945 FIXTURE_SETUP(audit)
2946 {
2947 struct protocol_variant prot_unspec = variant->prot;
2948
2949 prot_unspec.domain = AF_UNSPEC;
2950
2951 ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0));
2952 ASSERT_EQ(0, set_service(&self->srv1, variant->prot, 1));
2953 ASSERT_EQ(0, set_service(&self->srv2, variant->prot, 2));
2954 ASSERT_EQ(0, set_service(&self->unspec_srv0, prot_unspec, 0));
2955
2956 setup_loopback(_metadata);
2957
2958 set_cap(_metadata, CAP_AUDIT_CONTROL);
2959 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
2960 EXPECT_LE(0, self->audit_fd);
2961 disable_caps(_metadata);
2962 };
2963
FIXTURE_TEARDOWN(audit)2964 FIXTURE_TEARDOWN(audit)
2965 {
2966 set_cap(_metadata, CAP_AUDIT_CONTROL);
2967 EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter));
2968 clear_cap(_metadata, CAP_AUDIT_CONTROL);
2969 }
2970
TEST_F(audit,bind)2971 TEST_F(audit, bind)
2972 {
2973 const char *audit_evt = (variant->prot.type == SOCK_STREAM ?
2974 "net\\.bind_tcp" :
2975 "net\\.bind_udp");
2976 const __u64 access_rights =
2977 (variant->prot.type == SOCK_STREAM ?
2978 LANDLOCK_ACCESS_NET_BIND_TCP |
2979 LANDLOCK_ACCESS_NET_CONNECT_TCP :
2980 LANDLOCK_ACCESS_NET_BIND_UDP |
2981 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
2982 const struct landlock_ruleset_attr ruleset_attr = {
2983 .handled_access_net = access_rights,
2984 .quiet_access_net = access_rights,
2985 };
2986 const struct landlock_net_port_attr quiet_rule = {
2987 .allowed_access = 0,
2988 .port = self->srv2.port,
2989 };
2990 struct audit_records records;
2991 int ruleset_fd, sock_fd;
2992
2993 ruleset_fd =
2994 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2995 ASSERT_LE(0, ruleset_fd);
2996 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
2997 &quiet_rule, LANDLOCK_ADD_RULE_QUIET));
2998 enforce_ruleset(_metadata, ruleset_fd);
2999 EXPECT_EQ(0, close(ruleset_fd));
3000
3001 sock_fd = socket_variant(&self->srv0);
3002 ASSERT_LE(0, sock_fd);
3003 EXPECT_EQ(-EACCES, bind_variant(sock_fd, &self->srv0));
3004 EXPECT_EQ(0, matches_auditlog(self->audit_fd, audit_evt, "saddr",
3005 variant->addr, "src", self->srv0.port));
3006
3007 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3008 EXPECT_EQ(0, records.access);
3009 EXPECT_EQ(1, records.domain);
3010
3011 EXPECT_EQ(0, close(sock_fd));
3012
3013 /* Bind to srv2 (with quiet rule): no new audit logs. */
3014 sock_fd = socket_variant(&self->srv2);
3015 ASSERT_LE(0, sock_fd);
3016 EXPECT_EQ(-EACCES, bind_variant(sock_fd, &self->srv2));
3017
3018 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3019 EXPECT_EQ(0, records.access);
3020 EXPECT_EQ(0, records.domain);
3021
3022 EXPECT_EQ(0, close(sock_fd));
3023 }
3024
TEST_F(audit,connect)3025 TEST_F(audit, connect)
3026 {
3027 const char *audit_evt = (variant->prot.type == SOCK_STREAM ?
3028 "net\\.connect_tcp" :
3029 "net\\.connect_send_udp");
3030 const __u64 bind_right = (variant->prot.type == SOCK_STREAM ?
3031 LANDLOCK_ACCESS_NET_BIND_TCP :
3032 LANDLOCK_ACCESS_NET_BIND_UDP);
3033 const __u64 conn_right = (variant->prot.type == SOCK_STREAM ?
3034 LANDLOCK_ACCESS_NET_CONNECT_TCP :
3035 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
3036 const __u64 access_rights = bind_right | conn_right;
3037 const struct landlock_ruleset_attr ruleset_attr = {
3038 .handled_access_net = access_rights,
3039 .quiet_access_net = access_rights,
3040 };
3041 const struct landlock_net_port_attr rule_connect_p1 = {
3042 .allowed_access = conn_right,
3043 .port = self->srv1.port,
3044 };
3045 const struct landlock_net_port_attr quiet_rule = {
3046 .allowed_access = 0,
3047 .port = self->srv2.port,
3048 };
3049 struct audit_records records;
3050 int ruleset_fd, sock_fd;
3051
3052 ruleset_fd =
3053 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
3054 ASSERT_LE(0, ruleset_fd);
3055 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3056 &rule_connect_p1, 0));
3057 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3058 &quiet_rule, LANDLOCK_ADD_RULE_QUIET));
3059 enforce_ruleset(_metadata, ruleset_fd);
3060 EXPECT_EQ(0, close(ruleset_fd));
3061
3062 sock_fd = socket_variant(&self->srv0);
3063 ASSERT_LE(0, sock_fd);
3064 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv0));
3065 EXPECT_EQ(0, matches_auditlog(self->audit_fd, audit_evt, "daddr",
3066 variant->addr, "dest", self->srv0.port));
3067
3068 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3069 EXPECT_EQ(0, records.access);
3070 EXPECT_EQ(1, records.domain);
3071
3072 if (variant->prot.type == SOCK_DGRAM) {
3073 /* Check that autobind generates a denied bind event. */
3074 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv1));
3075
3076 EXPECT_EQ(0, matches_auditlog(self->audit_fd, "net\\.bind_udp",
3077 NULL, NULL, NULL, 0));
3078 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3079 EXPECT_EQ(0, records.access);
3080 EXPECT_EQ(0, records.domain);
3081 }
3082
3083 EXPECT_EQ(0, close(sock_fd));
3084
3085 /* Connect to srv2 (with quiet rule): no new audit logs. */
3086 sock_fd = socket_variant(&self->srv2);
3087 ASSERT_LE(0, sock_fd);
3088 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv2));
3089
3090 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3091 EXPECT_EQ(0, records.access);
3092 EXPECT_EQ(0, records.domain);
3093
3094 EXPECT_EQ(0, close(sock_fd));
3095 }
3096
3097 /* Quieting bind access has no effect on connect. */
TEST_F(audit,connect_quiet_bind)3098 TEST_F(audit, connect_quiet_bind)
3099 {
3100 const char *audit_evt = (variant->prot.type == SOCK_STREAM ?
3101 "net\\.connect_tcp" :
3102 "net\\.connect_send_udp");
3103 const int bind_right = (variant->prot.type == SOCK_STREAM ?
3104 LANDLOCK_ACCESS_NET_BIND_TCP :
3105 LANDLOCK_ACCESS_NET_BIND_UDP);
3106 const int conn_right = (variant->prot.type == SOCK_STREAM ?
3107 LANDLOCK_ACCESS_NET_CONNECT_TCP :
3108 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
3109 const int access_rights = bind_right | conn_right;
3110 const struct landlock_ruleset_attr ruleset_attr = {
3111 .handled_access_net = access_rights,
3112 .quiet_access_net = bind_right,
3113 };
3114 const struct landlock_ruleset_attr ruleset_attr_2 = {
3115 .handled_access_net = access_rights,
3116 .quiet_access_net = conn_right,
3117 };
3118 const struct landlock_net_port_attr quiet_rule = {
3119 .allowed_access = 0,
3120 .port = self->srv2.port,
3121 };
3122 struct audit_records records;
3123 int ruleset_fd, sock_fd;
3124
3125 ruleset_fd =
3126 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
3127 ASSERT_LE(0, ruleset_fd);
3128 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3129 &quiet_rule, LANDLOCK_ADD_RULE_QUIET));
3130 enforce_ruleset(_metadata, ruleset_fd);
3131 EXPECT_EQ(0, close(ruleset_fd));
3132
3133 sock_fd = socket_variant(&self->srv2);
3134 ASSERT_LE(0, sock_fd);
3135 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv2));
3136 EXPECT_EQ(0, matches_auditlog(self->audit_fd, audit_evt, "daddr",
3137 variant->addr, "dest", self->srv2.port));
3138
3139 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3140 EXPECT_EQ(0, records.access);
3141
3142 EXPECT_EQ(0, close(sock_fd));
3143
3144 /* New layer that also denies connect but has the correct quiet bit. */
3145 ruleset_fd = landlock_create_ruleset(&ruleset_attr_2,
3146 sizeof(ruleset_attr_2), 0);
3147 ASSERT_LE(0, ruleset_fd);
3148 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3149 &quiet_rule, LANDLOCK_ADD_RULE_QUIET));
3150 enforce_ruleset(_metadata, ruleset_fd);
3151 EXPECT_EQ(0, close(ruleset_fd));
3152
3153 sock_fd = socket_variant(&self->srv2);
3154 ASSERT_LE(0, sock_fd);
3155 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv2));
3156
3157 /* Quieted - no logs expected. */
3158 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3159 EXPECT_EQ(0, records.access);
3160
3161 EXPECT_EQ(0, close(sock_fd));
3162 }
3163
matches_log_connect_bound(int audit_fd,const char * const blockers,const char * const addr,__u16 lport,__u16 dport)3164 static int matches_log_connect_bound(int audit_fd, const char *const blockers,
3165 const char *const addr, __u16 lport,
3166 __u16 dport)
3167 {
3168 static const char log_template[] = REGEX_LANDLOCK_PREFIX
3169 " blockers=%s laddr=%s lport=%u daddr=%s dest=%u$";
3170 /* Slack for the blockers, two addresses and two port numbers. */
3171 char log_match[sizeof(log_template) + 60];
3172 int log_match_len;
3173
3174 log_match_len = snprintf(log_match, sizeof(log_match), log_template,
3175 blockers, addr, lport, addr, dport);
3176 if (log_match_len > sizeof(log_match))
3177 return -E2BIG;
3178
3179 return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
3180 NULL);
3181 }
3182
3183 /*
3184 * After a bind() to an allowed port, a denied connect must report laddr/lport
3185 * from the bound socket (made available through audit_net.sk) in addition to
3186 * the connect sockaddr's daddr/dest.
3187 */
TEST_F(audit,connect_bound)3188 TEST_F(audit, connect_bound)
3189 {
3190 const __u64 bind_right = (variant->prot.type == SOCK_STREAM ?
3191 LANDLOCK_ACCESS_NET_BIND_TCP :
3192 LANDLOCK_ACCESS_NET_BIND_UDP);
3193 const __u64 conn_right = (variant->prot.type == SOCK_STREAM ?
3194 LANDLOCK_ACCESS_NET_CONNECT_TCP :
3195 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP);
3196 const char *const audit_evt = (variant->prot.type == SOCK_STREAM ?
3197 "net\\.connect_tcp" :
3198 "net\\.connect_send_udp");
3199 const struct landlock_ruleset_attr ruleset_attr = {
3200 .handled_access_net = bind_right | conn_right,
3201 };
3202 const struct landlock_net_port_attr rule_bind = {
3203 .allowed_access = bind_right,
3204 .port = self->srv0.port,
3205 };
3206 struct service_fixture srv_remote;
3207 struct audit_records records;
3208 int ruleset_fd, sock_fd;
3209
3210 /* Uses a second port as the denied connect target. */
3211 ASSERT_EQ(0, set_service(&srv_remote, variant->prot, 1));
3212
3213 ruleset_fd =
3214 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
3215 ASSERT_LE(0, ruleset_fd);
3216 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3217 &rule_bind, 0));
3218 enforce_ruleset(_metadata, ruleset_fd);
3219 EXPECT_EQ(0, close(ruleset_fd));
3220
3221 sock_fd = socket_variant(&self->srv0);
3222 ASSERT_LE(0, sock_fd);
3223 EXPECT_EQ(0, bind_variant(sock_fd, &self->srv0));
3224 EXPECT_EQ(-EACCES, connect_variant(sock_fd, &srv_remote));
3225 EXPECT_EQ(0, matches_log_connect_bound(self->audit_fd, audit_evt,
3226 variant->addr, self->srv0.port,
3227 srv_remote.port));
3228
3229 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3230 EXPECT_EQ(0, records.access);
3231 EXPECT_EQ(1, records.domain);
3232
3233 EXPECT_EQ(0, close(sock_fd));
3234 }
3235
TEST_F(audit,sendmsg)3236 TEST_F(audit, sendmsg)
3237 {
3238 const struct landlock_ruleset_attr ruleset_attr = {
3239 .handled_access_net = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP |
3240 LANDLOCK_ACCESS_NET_BIND_UDP,
3241 };
3242 const struct landlock_net_port_attr rule = {
3243 .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
3244 .port = self->srv1.port,
3245 };
3246 struct audit_records records;
3247 int ruleset_fd;
3248 int sock_fd;
3249
3250 /* Sendmsg on stream sockets is never denied. */
3251 if (variant->prot.type != SOCK_DGRAM)
3252 return;
3253
3254 ruleset_fd =
3255 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
3256 ASSERT_LE(0, ruleset_fd);
3257 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3258 &rule, 0));
3259 enforce_ruleset(_metadata, ruleset_fd);
3260 EXPECT_EQ(0, close(ruleset_fd));
3261
3262 sock_fd = socket_variant(&self->srv0);
3263 ASSERT_LE(0, sock_fd);
3264 EXPECT_EQ(-EACCES, sendto_variant(sock_fd, &self->srv0, "A", 1, 0));
3265 EXPECT_EQ(0, matches_auditlog(self->audit_fd, "net\\.connect_send_udp",
3266 "daddr", variant->addr, "dest",
3267 self->srv0.port));
3268
3269 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3270 EXPECT_EQ(0, records.access);
3271 EXPECT_EQ(1, records.domain);
3272
3273 /* Check that autobind generates a denied bind event. */
3274 EXPECT_EQ(-EACCES, sendto_variant(sock_fd, &self->srv1, "A", 1, 0));
3275 EXPECT_EQ(0, matches_auditlog(self->audit_fd, "net\\.bind_udp", NULL,
3276 NULL, NULL, 0));
3277 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3278 EXPECT_EQ(0, records.access);
3279 EXPECT_EQ(0, records.domain);
3280
3281 EXPECT_EQ(-EACCES,
3282 sendto_variant(sock_fd, &self->unspec_srv0, "B", 1, 0));
3283 EXPECT_EQ(0, matches_auditlog(self->audit_fd, "net\\.connect_send_udp",
3284 "daddr", NULL, "dest", 0));
3285 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
3286 EXPECT_EQ(0, records.access);
3287 EXPECT_EQ(0, records.domain);
3288
3289 EXPECT_EQ(0, close(sock_fd));
3290 }
3291
3292 /* Trace tests */
3293
3294 /* clang-format off */
FIXTURE(trace_net)3295 FIXTURE(trace_net) {
3296 /* clang-format on */
3297 int tracefs_ok;
3298 };
3299
FIXTURE_SETUP(trace_net)3300 FIXTURE_SETUP(trace_net)
3301 {
3302 int ret;
3303
3304 /* Isolate the network namespace so the bound port cannot collide. */
3305 setup_loopback(_metadata);
3306
3307 set_cap(_metadata, CAP_SYS_ADMIN);
3308 ASSERT_EQ(0, unshare(CLONE_NEWNS));
3309 ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
3310
3311 ret = tracefs_fixture_setup();
3312 if (ret) {
3313 clear_cap(_metadata, CAP_SYS_ADMIN);
3314 self->tracefs_ok = 0;
3315 SKIP(return, "tracefs not available");
3316 }
3317 self->tracefs_ok = 1;
3318
3319 ASSERT_EQ(0,
3320 tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, true));
3321 ASSERT_EQ(0, tracefs_clear());
3322 clear_cap(_metadata, CAP_SYS_ADMIN);
3323 }
3324
FIXTURE_TEARDOWN(trace_net)3325 FIXTURE_TEARDOWN(trace_net)
3326 {
3327 if (!self->tracefs_ok)
3328 return;
3329
3330 set_cap(_metadata, CAP_SYS_ADMIN);
3331 tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, false);
3332 tracefs_fixture_teardown();
3333 clear_cap(_metadata, CAP_SYS_ADMIN);
3334 }
3335
3336 /*
3337 * Baseline: verifies that without Landlock, the bind succeeds and no
3338 * deny_access_net trace event fires.
3339 */
3340 /* clang-format off */
FIXTURE_VARIANT(trace_net)3341 FIXTURE_VARIANT(trace_net)
3342 {
3343 /* clang-format on */
3344 bool sandbox;
3345 int bind_port_offset; /* 0 = allowed port, 1 = denied port */
3346 int expect_denied;
3347 };
3348
3349 /* Unsandboxed: no Landlock, bind should succeed with no events. */
3350 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net,unsandboxed)3351 FIXTURE_VARIANT_ADD(trace_net, unsandboxed) {
3352 /* clang-format on */
3353 .sandbox = false,
3354 .bind_port_offset = 0,
3355 .expect_denied = 0,
3356 };
3357
3358 /* Denied: sandboxed, bind to port not in ruleset. */
3359 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net,bind_denied)3360 FIXTURE_VARIANT_ADD(trace_net, bind_denied) {
3361 /* clang-format on */
3362 .sandbox = true,
3363 .bind_port_offset = 1,
3364 .expect_denied = 1,
3365 };
3366
3367 /* Allowed: sandboxed, bind to port in ruleset. */
3368 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net,bind_allowed)3369 FIXTURE_VARIANT_ADD(trace_net, bind_allowed) {
3370 /* clang-format on */
3371 .sandbox = true,
3372 .bind_port_offset = 0,
3373 .expect_denied = 0,
3374 };
3375
TEST_F(trace_net,deny_access_net_bind)3376 TEST_F(trace_net, deny_access_net_bind)
3377 {
3378 char *buf;
3379 int count, status;
3380 pid_t child;
3381
3382 if (!self->tracefs_ok)
3383 SKIP(return, "tracefs not available");
3384
3385 ASSERT_EQ(0, tracefs_clear_buf());
3386
3387 child = fork();
3388 ASSERT_LE(0, child);
3389
3390 if (child == 0) {
3391 struct sockaddr_in addr = {
3392 .sin_family = AF_INET,
3393 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
3394 };
3395 int sock_fd;
3396
3397 if (variant->sandbox) {
3398 struct landlock_ruleset_attr ruleset_attr = {
3399 .handled_access_net =
3400 LANDLOCK_ACCESS_NET_BIND_TCP,
3401 };
3402 struct landlock_net_port_attr port_attr = {
3403 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
3404 .port = sock_port_start,
3405 };
3406 int ruleset_fd;
3407
3408 ruleset_fd = landlock_create_ruleset(
3409 &ruleset_attr, sizeof(ruleset_attr), 0);
3410 if (ruleset_fd < 0)
3411 _exit(1);
3412
3413 if (landlock_add_rule(ruleset_fd,
3414 LANDLOCK_RULE_NET_PORT,
3415 &port_attr, 0)) {
3416 close(ruleset_fd);
3417 _exit(1);
3418 }
3419
3420 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3421 if (landlock_restrict_self(ruleset_fd, 0)) {
3422 close(ruleset_fd);
3423 _exit(1);
3424 }
3425 close(ruleset_fd);
3426 }
3427
3428 sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3429 if (sock_fd < 0)
3430 _exit(1);
3431
3432 addr.sin_port =
3433 htons(sock_port_start + variant->bind_port_offset);
3434 if (variant->expect_denied) {
3435 /* Bind should be denied. */
3436 if (bind(sock_fd, (struct sockaddr *)&addr,
3437 sizeof(addr)) == 0) {
3438 close(sock_fd);
3439 _exit(2);
3440 }
3441 if (errno != EACCES) {
3442 close(sock_fd);
3443 _exit(3);
3444 }
3445 } else {
3446 /* Bind should succeed. */
3447 if (bind(sock_fd, (struct sockaddr *)&addr,
3448 sizeof(addr))) {
3449 close(sock_fd);
3450 _exit(2);
3451 }
3452 }
3453 close(sock_fd);
3454 _exit(0);
3455 }
3456
3457 ASSERT_EQ(child, waitpid(child, &status, 0));
3458 ASSERT_TRUE(WIFEXITED(status));
3459 EXPECT_EQ(0, WEXITSTATUS(status));
3460
3461 buf = tracefs_read_buf();
3462 ASSERT_NE(NULL, buf);
3463
3464 count = tracefs_count_matches(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK));
3465 if (variant->expect_denied) {
3466 EXPECT_EQ(variant->expect_denied, count)
3467 {
3468 TH_LOG("Expected deny_access_net event, got %d\n%s",
3469 count, buf);
3470 }
3471 } else {
3472 EXPECT_EQ(0, count)
3473 {
3474 TH_LOG("Expected 0 deny_access_net events, "
3475 "got %d\n%s",
3476 count, buf);
3477 }
3478 }
3479
3480 free(buf);
3481 }
3482
3483 /*
3484 * Anchors the denial fields shared by every deny_access_net event so a port
3485 * test also proves the denying domain, execution status, logging verdict, and
3486 * exact blocked access.
3487 */
3488 static void
expect_net_deny_common_fields(struct __test_metadata * const _metadata,const char * const buf,const char * const expected_blockers)3489 expect_net_deny_common_fields(struct __test_metadata *const _metadata,
3490 const char *const buf,
3491 const char *const expected_blockers)
3492 {
3493 char field[64];
3494
3495 ASSERT_EQ(0,
3496 tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
3497 "domain", field, sizeof(field)));
3498 EXPECT_STRNE("0", field);
3499
3500 /* Same exec that restricted itself, no exec in between. */
3501 ASSERT_EQ(0,
3502 tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
3503 "same_exec", field, sizeof(field)));
3504 EXPECT_STREQ("1", field);
3505
3506 /* Default flags, same exec: audit would log this denial. */
3507 ASSERT_EQ(0,
3508 tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
3509 "logged", field, sizeof(field)));
3510 EXPECT_STREQ("1", field);
3511
3512 ASSERT_EQ(0,
3513 tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
3514 "blockers", field, sizeof(field)));
3515 EXPECT_STREQ(expected_blockers, field);
3516 }
3517
3518 enum trace_net_operation {
3519 TRACE_NET_BIND,
3520 TRACE_NET_SEND,
3521 };
3522
3523 /* clang-format off */
FIXTURE(trace_net_address)3524 FIXTURE(trace_net_address) {
3525 /* clang-format on */
3526 int tracefs_ok;
3527 };
3528
FIXTURE_SETUP(trace_net_address)3529 FIXTURE_SETUP(trace_net_address)
3530 {
3531 int ret;
3532
3533 /* Isolate the network namespace so the bound port cannot collide. */
3534 setup_loopback(_metadata);
3535
3536 set_cap(_metadata, CAP_SYS_ADMIN);
3537 ASSERT_EQ(0, unshare(CLONE_NEWNS));
3538 ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
3539
3540 ret = tracefs_fixture_setup();
3541 if (ret) {
3542 clear_cap(_metadata, CAP_SYS_ADMIN);
3543 self->tracefs_ok = 0;
3544 SKIP(return, "tracefs not available");
3545 }
3546 self->tracefs_ok = 1;
3547
3548 ASSERT_EQ(0,
3549 tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, true));
3550 ASSERT_EQ(0, tracefs_clear());
3551 clear_cap(_metadata, CAP_SYS_ADMIN);
3552 }
3553
FIXTURE_TEARDOWN(trace_net_address)3554 FIXTURE_TEARDOWN(trace_net_address)
3555 {
3556 if (!self->tracefs_ok)
3557 return;
3558
3559 set_cap(_metadata, CAP_SYS_ADMIN);
3560 tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, false);
3561 tracefs_fixture_teardown();
3562 clear_cap(_metadata, CAP_SYS_ADMIN);
3563 }
3564
3565 /* clang-format off */
FIXTURE_VARIANT(trace_net_address)3566 FIXTURE_VARIANT(trace_net_address) {
3567 /* clang-format on */
3568 int socket_family;
3569 int socket_type;
3570 enum trace_net_operation operation;
3571 int address_family;
3572 socklen_t addrlen;
3573 __u64 handled_access;
3574 const char *expected_blockers;
3575 bool address_port_zero;
3576 bool expected_address_port;
3577 int expected_port;
3578 };
3579
3580 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net_address,ipv4_tcp_bind)3581 FIXTURE_VARIANT_ADD(trace_net_address, ipv4_tcp_bind) {
3582 /* clang-format on */
3583 .socket_family = AF_INET,
3584 .socket_type = SOCK_STREAM,
3585 .operation = TRACE_NET_BIND,
3586 .address_family = AF_INET,
3587 .addrlen = sizeof(struct sockaddr_in),
3588 .handled_access = LANDLOCK_ACCESS_NET_BIND_TCP,
3589 .expected_blockers = "bind_tcp",
3590 .expected_address_port = true,
3591 };
3592
3593 /* Explicit bind(0) has a checked zero port. */
3594 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net_address,ipv4_udp_bind_zero)3595 FIXTURE_VARIANT_ADD(trace_net_address, ipv4_udp_bind_zero) {
3596 /* clang-format on */
3597 .socket_family = AF_INET,
3598 .socket_type = SOCK_DGRAM,
3599 .operation = TRACE_NET_BIND,
3600 .address_family = AF_INET,
3601 .addrlen = sizeof(struct sockaddr_in),
3602 .handled_access = LANDLOCK_ACCESS_NET_BIND_UDP,
3603 .expected_blockers = "bind_udp",
3604 .address_port_zero = true,
3605 .expected_port = 0,
3606 };
3607
3608 /* A UDP send can deny its synthetic unspecified bind endpoint. */
3609 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net_address,ipv6_udp_autobind)3610 FIXTURE_VARIANT_ADD(trace_net_address, ipv6_udp_autobind) {
3611 /* clang-format on */
3612 .socket_family = AF_INET6,
3613 .socket_type = SOCK_DGRAM,
3614 .operation = TRACE_NET_SEND,
3615 .address_family = AF_INET6,
3616 .addrlen = sizeof(struct sockaddr_in6),
3617 .handled_access = LANDLOCK_ACCESS_NET_BIND_UDP,
3618 .expected_blockers = "bind_udp",
3619 .expected_port = 0,
3620 };
3621
3622 /* A family-only address has no checked port. */
3623 /* clang-format off */
FIXTURE_VARIANT_ADD(trace_net_address,ipv6_unspec_udp_send_min)3624 FIXTURE_VARIANT_ADD(trace_net_address, ipv6_unspec_udp_send_min) {
3625 /* clang-format on */
3626 .socket_family = AF_INET6,
3627 .socket_type = SOCK_DGRAM,
3628 .operation = TRACE_NET_SEND,
3629 .address_family = AF_UNSPEC,
3630 .addrlen = sizeof(sa_family_t),
3631 .handled_access = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP,
3632 .expected_blockers = "connect_send_udp",
3633 .expected_port = -1,
3634 };
3635
set_trace_net_address(struct sockaddr_storage * const storage,const int socket_family,const int address_family,const unsigned short port)3636 static void set_trace_net_address(struct sockaddr_storage *const storage,
3637 const int socket_family,
3638 const int address_family,
3639 const unsigned short port)
3640 {
3641 memset(storage, 0, sizeof(*storage));
3642
3643 if (socket_family == AF_INET) {
3644 struct sockaddr_in *const addr4 = (struct sockaddr_in *)storage;
3645
3646 addr4->sin_family = address_family;
3647 addr4->sin_port = htons(port);
3648 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3649 } else {
3650 struct sockaddr_in6 *const addr6 =
3651 (struct sockaddr_in6 *)storage;
3652
3653 addr6->sin6_family = address_family;
3654 addr6->sin6_port = htons(port);
3655 addr6->sin6_addr = in6addr_loopback;
3656 }
3657 }
3658
3659 /* Verifies the actionable signed port for representative checked shapes. */
TEST_F(trace_net_address,deny_access_net)3660 TEST_F(trace_net_address, deny_access_net)
3661 {
3662 const char *const event_regex = REGEX_DENY_ACCESS_NET(TRACE_TASK);
3663 const unsigned short address_port =
3664 variant->address_port_zero ? 0 : sock_port_start + 1;
3665 const int expected_port = variant->expected_address_port ?
3666 address_port :
3667 variant->expected_port;
3668 const struct landlock_ruleset_attr ruleset_attr = {
3669 .handled_access_net = variant->handled_access,
3670 };
3671 struct sockaddr_storage address;
3672 char field[64], expected[16];
3673 char *buf;
3674 int count, ret, ruleset_fd, socket_fd, status;
3675 pid_t child;
3676
3677 if (!self->tracefs_ok)
3678 SKIP(return, "tracefs not available");
3679
3680 set_trace_net_address(&address, variant->socket_family,
3681 variant->address_family, address_port);
3682 socket_fd = socket(variant->socket_family,
3683 variant->socket_type | SOCK_CLOEXEC, 0);
3684 ASSERT_LE(0, socket_fd);
3685 ruleset_fd =
3686 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
3687 ASSERT_LE(0, ruleset_fd);
3688 ASSERT_EQ(0, tracefs_clear_buf());
3689
3690 child = fork();
3691 ASSERT_LE(0, child);
3692 if (child == 0) {
3693 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
3694 _exit(1);
3695 if (landlock_restrict_self(ruleset_fd, 0))
3696 _exit(2);
3697 close(ruleset_fd);
3698
3699 switch (variant->operation) {
3700 case TRACE_NET_BIND:
3701 ret = bind(socket_fd, (const struct sockaddr *)&address,
3702 variant->addrlen);
3703 break;
3704 case TRACE_NET_SEND:
3705 ret = sendto(socket_fd, "A", 1, MSG_NOSIGNAL,
3706 (const struct sockaddr *)&address,
3707 variant->addrlen);
3708 break;
3709 default:
3710 _exit(3);
3711 }
3712 if (ret >= 0 || errno != EACCES)
3713 _exit(4);
3714 close(socket_fd);
3715
3716 _exit(0);
3717 }
3718 close(ruleset_fd);
3719 close(socket_fd);
3720
3721 ASSERT_EQ(child, waitpid(child, &status, 0));
3722 ASSERT_TRUE(WIFEXITED(status));
3723 ASSERT_EQ(0, WEXITSTATUS(status));
3724
3725 buf = tracefs_read_buf();
3726 ASSERT_NE(NULL, buf);
3727 count = tracefs_count_matches(buf, event_regex);
3728 if (count != 1)
3729 TH_LOG("Expected 1 denial event, got %d\n%s", count, buf);
3730 ASSERT_EQ(1, count);
3731 expect_net_deny_common_fields(_metadata, buf,
3732 variant->expected_blockers);
3733
3734 ASSERT_EQ(0, tracefs_extract_field(buf, event_regex, "port", field,
3735 sizeof(field)));
3736 snprintf(expected, sizeof(expected), "%d", expected_port);
3737 EXPECT_STREQ(expected, field);
3738
3739 free(buf);
3740 }
3741
3742 /* Field verification for the check_rule_net_port event on an allowed access. */
3743
3744 /* clang-format off */
FIXTURE(trace_net_check_rule)3745 FIXTURE(trace_net_check_rule) {
3746 /* clang-format on */
3747 int tracefs_ok;
3748 };
3749
FIXTURE_SETUP(trace_net_check_rule)3750 FIXTURE_SETUP(trace_net_check_rule)
3751 {
3752 int ret;
3753
3754 /* Isolate the network namespace so the bound port cannot collide. */
3755 setup_loopback(_metadata);
3756
3757 set_cap(_metadata, CAP_SYS_ADMIN);
3758 ASSERT_EQ(0, unshare(CLONE_NEWNS));
3759 ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
3760
3761 ret = tracefs_fixture_setup();
3762 if (ret) {
3763 clear_cap(_metadata, CAP_SYS_ADMIN);
3764 self->tracefs_ok = 0;
3765 SKIP(return, "tracefs not available");
3766 }
3767 self->tracefs_ok = 1;
3768
3769 ASSERT_EQ(0, tracefs_enable_event(TRACEFS_CHECK_RULE_NET_ENABLE, true));
3770 ASSERT_EQ(0, tracefs_clear());
3771 clear_cap(_metadata, CAP_SYS_ADMIN);
3772 }
3773
FIXTURE_TEARDOWN(trace_net_check_rule)3774 FIXTURE_TEARDOWN(trace_net_check_rule)
3775 {
3776 if (!self->tracefs_ok)
3777 return;
3778
3779 set_cap(_metadata, CAP_SYS_ADMIN);
3780 tracefs_enable_event(TRACEFS_CHECK_RULE_NET_ENABLE, false);
3781 tracefs_fixture_teardown();
3782 clear_cap(_metadata, CAP_SYS_ADMIN);
3783 }
3784
3785 /*
3786 * Verifies that an allowed bind matching a net-port rule emits exactly one
3787 * landlock_check_rule_net_port event with the enforcing domain, the requested
3788 * access, the checked port (host endianness), and the per-layer grants. The
3789 * whole event is anchored to exact values so removing the check_rule_net_port
3790 * emission or introducing a byte-order or field-plumbing regression fails the
3791 * test.
3792 */
TEST_F(trace_net_check_rule,check_rule_net_fields)3793 TEST_F(trace_net_check_rule, check_rule_net_fields)
3794 {
3795 pid_t child;
3796 int status;
3797 char *buf;
3798 char field[64], expected[16];
3799
3800 if (!self->tracefs_ok)
3801 SKIP(return, "tracefs not available");
3802
3803 child = fork();
3804 ASSERT_LE(0, child);
3805
3806 if (child == 0) {
3807 struct landlock_ruleset_attr ruleset_attr = {
3808 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
3809 };
3810 struct landlock_net_port_attr port_attr = {
3811 .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
3812 .port = sock_port_start,
3813 };
3814 struct sockaddr_in addr = {
3815 .sin_family = AF_INET,
3816 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
3817 };
3818 int ruleset_fd, sock_fd;
3819
3820 ruleset_fd = landlock_create_ruleset(&ruleset_attr,
3821 sizeof(ruleset_attr), 0);
3822 if (ruleset_fd < 0)
3823 _exit(1);
3824
3825 if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
3826 &port_attr, 0)) {
3827 close(ruleset_fd);
3828 _exit(1);
3829 }
3830
3831 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
3832 if (landlock_restrict_self(ruleset_fd, 0)) {
3833 close(ruleset_fd);
3834 _exit(1);
3835 }
3836 close(ruleset_fd);
3837
3838 /* Bind to the allowed port: succeeds and matches the rule. */
3839 sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3840 if (sock_fd < 0)
3841 _exit(1);
3842
3843 addr.sin_port = htons(sock_port_start);
3844 if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) {
3845 close(sock_fd);
3846 _exit(2);
3847 }
3848 close(sock_fd);
3849 _exit(0);
3850 }
3851
3852 ASSERT_EQ(child, waitpid(child, &status, 0));
3853 ASSERT_TRUE(WIFEXITED(status));
3854 EXPECT_EQ(0, WEXITSTATUS(status));
3855
3856 buf = tracefs_read_buf();
3857 ASSERT_NE(NULL, buf);
3858
3859 /* A single-layer domain matching one port rule emits one event. */
3860 EXPECT_EQ(1,
3861 tracefs_count_matches(buf, REGEX_CHECK_RULE_NET(TRACE_TASK)))
3862 {
3863 TH_LOG("Expected 1 check_rule_net_port event\n%s", buf);
3864 }
3865
3866 ASSERT_EQ(0,
3867 tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
3868 "domain", field, sizeof(field)));
3869 EXPECT_STRNE("0", field);
3870
3871 ASSERT_EQ(0, tracefs_extract_field(
3872 buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
3873 "access_request", field, sizeof(field)));
3874 EXPECT_STREQ("bind_tcp", field);
3875
3876 /*
3877 * The port is reported in host endianness (UAPI convention), so on
3878 * little-endian htons(sock_port_start) would print a different value:
3879 * the exact match also catches byte-order regressions.
3880 */
3881 ASSERT_EQ(0,
3882 tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
3883 "port", field, sizeof(field)));
3884 snprintf(expected, sizeof(expected), "%llu",
3885 (unsigned long long)sock_port_start);
3886 EXPECT_STREQ(expected, field);
3887
3888 /* One layer that fully grants the request: grants={bind_tcp}. */
3889 ASSERT_EQ(0,
3890 tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
3891 "grants", field, sizeof(field)));
3892 EXPECT_STREQ("{bind_tcp}", field);
3893
3894 free(buf);
3895 }
3896
3897 TEST_HARNESS_MAIN
3898