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