brintos

brintos / linux-shallow public Read only

0
0
Text · 30.3 KiB · a6b59d2 Raw
1042 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Landlock tests - Abstract UNIX socket4 *5 * Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com>6 */7 8#define _GNU_SOURCE9#include <errno.h>10#include <fcntl.h>11#include <linux/landlock.h>12#include <sched.h>13#include <signal.h>14#include <stddef.h>15#include <sys/prctl.h>16#include <sys/socket.h>17#include <sys/stat.h>18#include <sys/types.h>19#include <sys/un.h>20#include <sys/wait.h>21#include <unistd.h>22 23#include "common.h"24#include "scoped_common.h"25 26/* Number of pending connections queue to be hold. */27const short backlog = 10;28 29static void create_fs_domain(struct __test_metadata *const _metadata)30{31	int ruleset_fd;32	struct landlock_ruleset_attr ruleset_attr = {33		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR,34	};35 36	ruleset_fd =37		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);38	EXPECT_LE(0, ruleset_fd)39	{40		TH_LOG("Failed to create a ruleset: %s", strerror(errno));41	}42	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));43	EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));44	EXPECT_EQ(0, close(ruleset_fd));45}46 47FIXTURE(scoped_domains)48{49	struct service_fixture stream_address, dgram_address;50};51 52#include "scoped_base_variants.h"53 54FIXTURE_SETUP(scoped_domains)55{56	drop_caps(_metadata);57 58	memset(&self->stream_address, 0, sizeof(self->stream_address));59	memset(&self->dgram_address, 0, sizeof(self->dgram_address));60	set_unix_address(&self->stream_address, 0);61	set_unix_address(&self->dgram_address, 1);62}63 64FIXTURE_TEARDOWN(scoped_domains)65{66}67 68/*69 * Test unix_stream_connect() and unix_may_send() for a child connecting to its70 * parent, when they have scoped domain or no domain.71 */72TEST_F(scoped_domains, connect_to_parent)73{74	pid_t child;75	bool can_connect_to_parent;76	int status;77	int pipe_parent[2];78	int stream_server, dgram_server;79 80	/*81	 * can_connect_to_parent is true if a child process can connect to its82	 * parent process. This depends on the child process not being isolated83	 * from the parent with a dedicated Landlock domain.84	 */85	can_connect_to_parent = !variant->domain_child;86 87	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));88	if (variant->domain_both) {89		create_scoped_domain(_metadata,90				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);91		if (!__test_passed(_metadata))92			return;93	}94 95	child = fork();96	ASSERT_LE(0, child);97	if (child == 0) {98		int err;99		int stream_client, dgram_client;100		char buf_child;101 102		EXPECT_EQ(0, close(pipe_parent[1]));103		if (variant->domain_child)104			create_scoped_domain(105				_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);106 107		stream_client = socket(AF_UNIX, SOCK_STREAM, 0);108		ASSERT_LE(0, stream_client);109		dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);110		ASSERT_LE(0, dgram_client);111 112		/* Waits for the server. */113		ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));114 115		err = connect(stream_client, &self->stream_address.unix_addr,116			      self->stream_address.unix_addr_len);117		if (can_connect_to_parent) {118			EXPECT_EQ(0, err);119		} else {120			EXPECT_EQ(-1, err);121			EXPECT_EQ(EPERM, errno);122		}123		EXPECT_EQ(0, close(stream_client));124 125		err = connect(dgram_client, &self->dgram_address.unix_addr,126			      self->dgram_address.unix_addr_len);127		if (can_connect_to_parent) {128			EXPECT_EQ(0, err);129		} else {130			EXPECT_EQ(-1, err);131			EXPECT_EQ(EPERM, errno);132		}133		EXPECT_EQ(0, close(dgram_client));134		_exit(_metadata->exit_code);135		return;136	}137	EXPECT_EQ(0, close(pipe_parent[0]));138	if (variant->domain_parent)139		create_scoped_domain(_metadata,140				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);141 142	stream_server = socket(AF_UNIX, SOCK_STREAM, 0);143	ASSERT_LE(0, stream_server);144	dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0);145	ASSERT_LE(0, dgram_server);146	ASSERT_EQ(0, bind(stream_server, &self->stream_address.unix_addr,147			  self->stream_address.unix_addr_len));148	ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr,149			  self->dgram_address.unix_addr_len));150	ASSERT_EQ(0, listen(stream_server, backlog));151 152	/* Signals to child that the parent is listening. */153	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));154 155	ASSERT_EQ(child, waitpid(child, &status, 0));156	EXPECT_EQ(0, close(stream_server));157	EXPECT_EQ(0, close(dgram_server));158 159	if (WIFSIGNALED(status) || !WIFEXITED(status) ||160	    WEXITSTATUS(status) != EXIT_SUCCESS)161		_metadata->exit_code = KSFT_FAIL;162}163 164/*165 * Test unix_stream_connect() and unix_may_send() for a parent connecting to166 * its child, when they have scoped domain or no domain.167 */168TEST_F(scoped_domains, connect_to_child)169{170	pid_t child;171	bool can_connect_to_child;172	int err_stream, err_dgram, errno_stream, errno_dgram, status;173	int pipe_child[2], pipe_parent[2];174	char buf;175	int stream_client, dgram_client;176 177	/*178	 * can_connect_to_child is true if a parent process can connect to its179	 * child process. The parent process is not isolated from the child180	 * with a dedicated Landlock domain.181	 */182	can_connect_to_child = !variant->domain_parent;183 184	ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));185	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));186	if (variant->domain_both) {187		create_scoped_domain(_metadata,188				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);189		if (!__test_passed(_metadata))190			return;191	}192 193	child = fork();194	ASSERT_LE(0, child);195	if (child == 0) {196		int stream_server, dgram_server;197 198		EXPECT_EQ(0, close(pipe_parent[1]));199		EXPECT_EQ(0, close(pipe_child[0]));200		if (variant->domain_child)201			create_scoped_domain(202				_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);203 204		/* Waits for the parent to be in a domain, if any. */205		ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));206 207		stream_server = socket(AF_UNIX, SOCK_STREAM, 0);208		ASSERT_LE(0, stream_server);209		dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0);210		ASSERT_LE(0, dgram_server);211		ASSERT_EQ(0,212			  bind(stream_server, &self->stream_address.unix_addr,213			       self->stream_address.unix_addr_len));214		ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr,215				  self->dgram_address.unix_addr_len));216		ASSERT_EQ(0, listen(stream_server, backlog));217 218		/* Signals to the parent that child is listening. */219		ASSERT_EQ(1, write(pipe_child[1], ".", 1));220 221		/* Waits to connect. */222		ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));223		EXPECT_EQ(0, close(stream_server));224		EXPECT_EQ(0, close(dgram_server));225		_exit(_metadata->exit_code);226		return;227	}228	EXPECT_EQ(0, close(pipe_child[1]));229	EXPECT_EQ(0, close(pipe_parent[0]));230 231	if (variant->domain_parent)232		create_scoped_domain(_metadata,233				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);234 235	/* Signals that the parent is in a domain, if any. */236	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));237 238	stream_client = socket(AF_UNIX, SOCK_STREAM, 0);239	ASSERT_LE(0, stream_client);240	dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);241	ASSERT_LE(0, dgram_client);242 243	/* Waits for the child to listen */244	ASSERT_EQ(1, read(pipe_child[0], &buf, 1));245	err_stream = connect(stream_client, &self->stream_address.unix_addr,246			     self->stream_address.unix_addr_len);247	errno_stream = errno;248	err_dgram = connect(dgram_client, &self->dgram_address.unix_addr,249			    self->dgram_address.unix_addr_len);250	errno_dgram = errno;251	if (can_connect_to_child) {252		EXPECT_EQ(0, err_stream);253		EXPECT_EQ(0, err_dgram);254	} else {255		EXPECT_EQ(-1, err_stream);256		EXPECT_EQ(-1, err_dgram);257		EXPECT_EQ(EPERM, errno_stream);258		EXPECT_EQ(EPERM, errno_dgram);259	}260	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));261	EXPECT_EQ(0, close(stream_client));262	EXPECT_EQ(0, close(dgram_client));263 264	ASSERT_EQ(child, waitpid(child, &status, 0));265	if (WIFSIGNALED(status) || !WIFEXITED(status) ||266	    WEXITSTATUS(status) != EXIT_SUCCESS)267		_metadata->exit_code = KSFT_FAIL;268}269 270FIXTURE(scoped_vs_unscoped)271{272	struct service_fixture parent_stream_address, parent_dgram_address,273		child_stream_address, child_dgram_address;274};275 276#include "scoped_multiple_domain_variants.h"277 278FIXTURE_SETUP(scoped_vs_unscoped)279{280	drop_caps(_metadata);281 282	memset(&self->parent_stream_address, 0,283	       sizeof(self->parent_stream_address));284	set_unix_address(&self->parent_stream_address, 0);285	memset(&self->parent_dgram_address, 0,286	       sizeof(self->parent_dgram_address));287	set_unix_address(&self->parent_dgram_address, 1);288	memset(&self->child_stream_address, 0,289	       sizeof(self->child_stream_address));290	set_unix_address(&self->child_stream_address, 2);291	memset(&self->child_dgram_address, 0,292	       sizeof(self->child_dgram_address));293	set_unix_address(&self->child_dgram_address, 3);294}295 296FIXTURE_TEARDOWN(scoped_vs_unscoped)297{298}299 300/*301 * Test unix_stream_connect and unix_may_send for parent, child and302 * grand child processes when they can have scoped or non-scoped domains.303 */304TEST_F(scoped_vs_unscoped, unix_scoping)305{306	pid_t child;307	int status;308	bool can_connect_to_parent, can_connect_to_child;309	int pipe_parent[2];310	int stream_server_parent, dgram_server_parent;311 312	can_connect_to_child = (variant->domain_grand_child != SCOPE_SANDBOX);313	can_connect_to_parent = (can_connect_to_child &&314				 (variant->domain_children != SCOPE_SANDBOX));315 316	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));317 318	if (variant->domain_all == OTHER_SANDBOX)319		create_fs_domain(_metadata);320	else if (variant->domain_all == SCOPE_SANDBOX)321		create_scoped_domain(_metadata,322				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);323 324	child = fork();325	ASSERT_LE(0, child);326	if (child == 0) {327		int stream_server_child, dgram_server_child;328		int pipe_child[2];329		pid_t grand_child;330 331		ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));332 333		if (variant->domain_children == OTHER_SANDBOX)334			create_fs_domain(_metadata);335		else if (variant->domain_children == SCOPE_SANDBOX)336			create_scoped_domain(337				_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);338 339		grand_child = fork();340		ASSERT_LE(0, grand_child);341		if (grand_child == 0) {342			char buf;343			int stream_err, dgram_err, stream_errno, dgram_errno;344			int stream_client, dgram_client;345 346			EXPECT_EQ(0, close(pipe_parent[1]));347			EXPECT_EQ(0, close(pipe_child[1]));348 349			if (variant->domain_grand_child == OTHER_SANDBOX)350				create_fs_domain(_metadata);351			else if (variant->domain_grand_child == SCOPE_SANDBOX)352				create_scoped_domain(353					_metadata,354					LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);355 356			stream_client = socket(AF_UNIX, SOCK_STREAM, 0);357			ASSERT_LE(0, stream_client);358			dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0);359			ASSERT_LE(0, dgram_client);360 361			ASSERT_EQ(1, read(pipe_child[0], &buf, 1));362			stream_err = connect(363				stream_client,364				&self->child_stream_address.unix_addr,365				self->child_stream_address.unix_addr_len);366			stream_errno = errno;367			dgram_err = connect(368				dgram_client,369				&self->child_dgram_address.unix_addr,370				self->child_dgram_address.unix_addr_len);371			dgram_errno = errno;372			if (can_connect_to_child) {373				EXPECT_EQ(0, stream_err);374				EXPECT_EQ(0, dgram_err);375			} else {376				EXPECT_EQ(-1, stream_err);377				EXPECT_EQ(-1, dgram_err);378				EXPECT_EQ(EPERM, stream_errno);379				EXPECT_EQ(EPERM, dgram_errno);380			}381 382			EXPECT_EQ(0, close(stream_client));383			stream_client = socket(AF_UNIX, SOCK_STREAM, 0);384			ASSERT_LE(0, stream_client);385			/* Datagram sockets can "reconnect". */386 387			ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));388			stream_err = connect(389				stream_client,390				&self->parent_stream_address.unix_addr,391				self->parent_stream_address.unix_addr_len);392			stream_errno = errno;393			dgram_err = connect(394				dgram_client,395				&self->parent_dgram_address.unix_addr,396				self->parent_dgram_address.unix_addr_len);397			dgram_errno = errno;398			if (can_connect_to_parent) {399				EXPECT_EQ(0, stream_err);400				EXPECT_EQ(0, dgram_err);401			} else {402				EXPECT_EQ(-1, stream_err);403				EXPECT_EQ(-1, dgram_err);404				EXPECT_EQ(EPERM, stream_errno);405				EXPECT_EQ(EPERM, dgram_errno);406			}407			EXPECT_EQ(0, close(stream_client));408			EXPECT_EQ(0, close(dgram_client));409 410			_exit(_metadata->exit_code);411			return;412		}413		EXPECT_EQ(0, close(pipe_child[0]));414		if (variant->domain_child == OTHER_SANDBOX)415			create_fs_domain(_metadata);416		else if (variant->domain_child == SCOPE_SANDBOX)417			create_scoped_domain(418				_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);419 420		stream_server_child = socket(AF_UNIX, SOCK_STREAM, 0);421		ASSERT_LE(0, stream_server_child);422		dgram_server_child = socket(AF_UNIX, SOCK_DGRAM, 0);423		ASSERT_LE(0, dgram_server_child);424 425		ASSERT_EQ(0, bind(stream_server_child,426				  &self->child_stream_address.unix_addr,427				  self->child_stream_address.unix_addr_len));428		ASSERT_EQ(0, bind(dgram_server_child,429				  &self->child_dgram_address.unix_addr,430				  self->child_dgram_address.unix_addr_len));431		ASSERT_EQ(0, listen(stream_server_child, backlog));432 433		ASSERT_EQ(1, write(pipe_child[1], ".", 1));434		ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0));435		EXPECT_EQ(0, close(stream_server_child))436		EXPECT_EQ(0, close(dgram_server_child));437		return;438	}439	EXPECT_EQ(0, close(pipe_parent[0]));440 441	if (variant->domain_parent == OTHER_SANDBOX)442		create_fs_domain(_metadata);443	else if (variant->domain_parent == SCOPE_SANDBOX)444		create_scoped_domain(_metadata,445				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);446 447	stream_server_parent = socket(AF_UNIX, SOCK_STREAM, 0);448	ASSERT_LE(0, stream_server_parent);449	dgram_server_parent = socket(AF_UNIX, SOCK_DGRAM, 0);450	ASSERT_LE(0, dgram_server_parent);451	ASSERT_EQ(0, bind(stream_server_parent,452			  &self->parent_stream_address.unix_addr,453			  self->parent_stream_address.unix_addr_len));454	ASSERT_EQ(0, bind(dgram_server_parent,455			  &self->parent_dgram_address.unix_addr,456			  self->parent_dgram_address.unix_addr_len));457 458	ASSERT_EQ(0, listen(stream_server_parent, backlog));459 460	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));461	ASSERT_EQ(child, waitpid(child, &status, 0));462	EXPECT_EQ(0, close(stream_server_parent));463	EXPECT_EQ(0, close(dgram_server_parent));464 465	if (WIFSIGNALED(status) || !WIFEXITED(status) ||466	    WEXITSTATUS(status) != EXIT_SUCCESS)467		_metadata->exit_code = KSFT_FAIL;468}469 470FIXTURE(outside_socket)471{472	struct service_fixture address, transit_address;473};474 475FIXTURE_VARIANT(outside_socket)476{477	const bool child_socket;478	const int type;479};480 481/* clang-format off */482FIXTURE_VARIANT_ADD(outside_socket, allow_dgram_child) {483	/* clang-format on */484	.child_socket = true,485	.type = SOCK_DGRAM,486};487 488/* clang-format off */489FIXTURE_VARIANT_ADD(outside_socket, deny_dgram_server) {490	/* clang-format on */491	.child_socket = false,492	.type = SOCK_DGRAM,493};494 495/* clang-format off */496FIXTURE_VARIANT_ADD(outside_socket, allow_stream_child) {497	/* clang-format on */498	.child_socket = true,499	.type = SOCK_STREAM,500};501 502/* clang-format off */503FIXTURE_VARIANT_ADD(outside_socket, deny_stream_server) {504	/* clang-format on */505	.child_socket = false,506	.type = SOCK_STREAM,507};508 509FIXTURE_SETUP(outside_socket)510{511	drop_caps(_metadata);512 513	memset(&self->transit_address, 0, sizeof(self->transit_address));514	set_unix_address(&self->transit_address, 0);515	memset(&self->address, 0, sizeof(self->address));516	set_unix_address(&self->address, 1);517}518 519FIXTURE_TEARDOWN(outside_socket)520{521}522 523/*524 * Test unix_stream_connect and unix_may_send for parent and child processes525 * when connecting socket has different domain than the process using it.526 */527TEST_F(outside_socket, socket_with_different_domain)528{529	pid_t child;530	int err, status;531	int pipe_child[2], pipe_parent[2];532	char buf_parent;533	int server_socket;534 535	ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));536	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));537 538	child = fork();539	ASSERT_LE(0, child);540	if (child == 0) {541		int client_socket;542		char buf_child;543 544		EXPECT_EQ(0, close(pipe_parent[1]));545		EXPECT_EQ(0, close(pipe_child[0]));546 547		/* Client always has a domain. */548		create_scoped_domain(_metadata,549				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);550 551		if (variant->child_socket) {552			int data_socket, passed_socket, stream_server;553 554			passed_socket = socket(AF_UNIX, variant->type, 0);555			ASSERT_LE(0, passed_socket);556			stream_server = socket(AF_UNIX, SOCK_STREAM, 0);557			ASSERT_LE(0, stream_server);558			ASSERT_EQ(0, bind(stream_server,559					  &self->transit_address.unix_addr,560					  self->transit_address.unix_addr_len));561			ASSERT_EQ(0, listen(stream_server, backlog));562			ASSERT_EQ(1, write(pipe_child[1], ".", 1));563			data_socket = accept(stream_server, NULL, NULL);564			ASSERT_LE(0, data_socket);565			ASSERT_EQ(0, send_fd(data_socket, passed_socket));566			EXPECT_EQ(0, close(passed_socket));567			EXPECT_EQ(0, close(stream_server));568		}569 570		client_socket = socket(AF_UNIX, variant->type, 0);571		ASSERT_LE(0, client_socket);572 573		/* Waits for parent signal for connection. */574		ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));575		err = connect(client_socket, &self->address.unix_addr,576			      self->address.unix_addr_len);577		if (variant->child_socket) {578			EXPECT_EQ(0, err);579		} else {580			EXPECT_EQ(-1, err);581			EXPECT_EQ(EPERM, errno);582		}583		EXPECT_EQ(0, close(client_socket));584		_exit(_metadata->exit_code);585		return;586	}587	EXPECT_EQ(0, close(pipe_child[1]));588	EXPECT_EQ(0, close(pipe_parent[0]));589 590	if (variant->child_socket) {591		int client_child = socket(AF_UNIX, SOCK_STREAM, 0);592 593		ASSERT_LE(0, client_child);594		ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1));595		ASSERT_EQ(0, connect(client_child,596				     &self->transit_address.unix_addr,597				     self->transit_address.unix_addr_len));598		server_socket = recv_fd(client_child);599		EXPECT_EQ(0, close(client_child));600	} else {601		server_socket = socket(AF_UNIX, variant->type, 0);602	}603	ASSERT_LE(0, server_socket);604 605	/* Server always has a domain. */606	create_scoped_domain(_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);607 608	ASSERT_EQ(0, bind(server_socket, &self->address.unix_addr,609			  self->address.unix_addr_len));610	if (variant->type == SOCK_STREAM)611		ASSERT_EQ(0, listen(server_socket, backlog));612 613	/* Signals to child that the parent is listening. */614	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));615 616	ASSERT_EQ(child, waitpid(child, &status, 0));617	EXPECT_EQ(0, close(server_socket));618 619	if (WIFSIGNALED(status) || !WIFEXITED(status) ||620	    WEXITSTATUS(status) != EXIT_SUCCESS)621		_metadata->exit_code = KSFT_FAIL;622}623 624static const char stream_path[] = TMP_DIR "/stream.sock";625static const char dgram_path[] = TMP_DIR "/dgram.sock";626 627/* clang-format off */628FIXTURE(various_address_sockets) {};629/* clang-format on */630 631FIXTURE_VARIANT(various_address_sockets)632{633	const int domain;634};635 636/* clang-format off */637FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_scoped_domain) {638	/* clang-format on */639	.domain = SCOPE_SANDBOX,640};641 642/* clang-format off */643FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_other_domain) {644	/* clang-format on */645	.domain = OTHER_SANDBOX,646};647 648/* clang-format off */649FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_no_domain) {650	/* clang-format on */651	.domain = NO_SANDBOX,652};653 654FIXTURE_SETUP(various_address_sockets)655{656	drop_caps(_metadata);657 658	umask(0077);659	ASSERT_EQ(0, mkdir(TMP_DIR, 0700));660}661 662FIXTURE_TEARDOWN(various_address_sockets)663{664	EXPECT_EQ(0, unlink(stream_path));665	EXPECT_EQ(0, unlink(dgram_path));666	EXPECT_EQ(0, rmdir(TMP_DIR));667}668 669TEST_F(various_address_sockets, scoped_pathname_sockets)670{671	socklen_t size_stream, size_dgram;672	pid_t child;673	int status;674	char buf_child, buf_parent;675	int pipe_parent[2];676	int unnamed_sockets[2];677	int stream_pathname_socket, dgram_pathname_socket,678		stream_abstract_socket, dgram_abstract_socket, data_socket;679	struct service_fixture stream_abstract_addr, dgram_abstract_addr;680	struct sockaddr_un stream_pathname_addr = {681		.sun_family = AF_UNIX,682	};683	struct sockaddr_un dgram_pathname_addr = {684		.sun_family = AF_UNIX,685	};686 687	/* Pathname address. */688	snprintf(stream_pathname_addr.sun_path,689		 sizeof(stream_pathname_addr.sun_path), "%s", stream_path);690	size_stream = offsetof(struct sockaddr_un, sun_path) +691		      strlen(stream_pathname_addr.sun_path);692	snprintf(dgram_pathname_addr.sun_path,693		 sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path);694	size_dgram = offsetof(struct sockaddr_un, sun_path) +695		     strlen(dgram_pathname_addr.sun_path);696 697	/* Abstract address. */698	memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr));699	set_unix_address(&stream_abstract_addr, 0);700	memset(&dgram_abstract_addr, 0, sizeof(dgram_abstract_addr));701	set_unix_address(&dgram_abstract_addr, 1);702 703	/* Unnamed address for datagram socket. */704	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_DGRAM, 0, unnamed_sockets));705 706	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));707 708	child = fork();709	ASSERT_LE(0, child);710	if (child == 0) {711		int err;712 713		EXPECT_EQ(0, close(pipe_parent[1]));714		EXPECT_EQ(0, close(unnamed_sockets[1]));715 716		if (variant->domain == SCOPE_SANDBOX)717			create_scoped_domain(718				_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);719		else if (variant->domain == OTHER_SANDBOX)720			create_fs_domain(_metadata);721 722		/* Waits for parent to listen. */723		ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1));724		EXPECT_EQ(0, close(pipe_parent[0]));725 726		/* Checks that we can send data through a datagram socket. */727		ASSERT_EQ(1, write(unnamed_sockets[0], "a", 1));728		EXPECT_EQ(0, close(unnamed_sockets[0]));729 730		/* Connects with pathname sockets. */731		stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);732		ASSERT_LE(0, stream_pathname_socket);733		ASSERT_EQ(0, connect(stream_pathname_socket,734				     &stream_pathname_addr, size_stream));735		ASSERT_EQ(1, write(stream_pathname_socket, "b", 1));736		EXPECT_EQ(0, close(stream_pathname_socket));737 738		/* Sends without connection. */739		dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);740		ASSERT_LE(0, dgram_pathname_socket);741		err = sendto(dgram_pathname_socket, "c", 1, 0,742			     &dgram_pathname_addr, size_dgram);743		EXPECT_EQ(1, err);744 745		/* Sends with connection. */746		ASSERT_EQ(0, connect(dgram_pathname_socket,747				     &dgram_pathname_addr, size_dgram));748		ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1));749		EXPECT_EQ(0, close(dgram_pathname_socket));750 751		/* Connects with abstract sockets. */752		stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);753		ASSERT_LE(0, stream_abstract_socket);754		err = connect(stream_abstract_socket,755			      &stream_abstract_addr.unix_addr,756			      stream_abstract_addr.unix_addr_len);757		if (variant->domain == SCOPE_SANDBOX) {758			EXPECT_EQ(-1, err);759			EXPECT_EQ(EPERM, errno);760		} else {761			EXPECT_EQ(0, err);762			ASSERT_EQ(1, write(stream_abstract_socket, "e", 1));763		}764		EXPECT_EQ(0, close(stream_abstract_socket));765 766		/* Sends without connection. */767		dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0);768		ASSERT_LE(0, dgram_abstract_socket);769		err = sendto(dgram_abstract_socket, "f", 1, 0,770			     &dgram_abstract_addr.unix_addr,771			     dgram_abstract_addr.unix_addr_len);772		if (variant->domain == SCOPE_SANDBOX) {773			EXPECT_EQ(-1, err);774			EXPECT_EQ(EPERM, errno);775		} else {776			EXPECT_EQ(1, err);777		}778 779		/* Sends with connection. */780		err = connect(dgram_abstract_socket,781			      &dgram_abstract_addr.unix_addr,782			      dgram_abstract_addr.unix_addr_len);783		if (variant->domain == SCOPE_SANDBOX) {784			EXPECT_EQ(-1, err);785			EXPECT_EQ(EPERM, errno);786		} else {787			EXPECT_EQ(0, err);788			ASSERT_EQ(1, write(dgram_abstract_socket, "g", 1));789		}790		EXPECT_EQ(0, close(dgram_abstract_socket));791 792		_exit(_metadata->exit_code);793		return;794	}795	EXPECT_EQ(0, close(pipe_parent[0]));796	EXPECT_EQ(0, close(unnamed_sockets[0]));797 798	/* Sets up pathname servers. */799	stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0);800	ASSERT_LE(0, stream_pathname_socket);801	ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr,802			  size_stream));803	ASSERT_EQ(0, listen(stream_pathname_socket, backlog));804 805	dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0);806	ASSERT_LE(0, dgram_pathname_socket);807	ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr,808			  size_dgram));809 810	/* Sets up abstract servers. */811	stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0);812	ASSERT_LE(0, stream_abstract_socket);813	ASSERT_EQ(0,814		  bind(stream_abstract_socket, &stream_abstract_addr.unix_addr,815		       stream_abstract_addr.unix_addr_len));816 817	dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0);818	ASSERT_LE(0, dgram_abstract_socket);819	ASSERT_EQ(0, bind(dgram_abstract_socket, &dgram_abstract_addr.unix_addr,820			  dgram_abstract_addr.unix_addr_len));821	ASSERT_EQ(0, listen(stream_abstract_socket, backlog));822 823	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));824	EXPECT_EQ(0, close(pipe_parent[1]));825 826	/* Reads from unnamed socket. */827	ASSERT_EQ(1, read(unnamed_sockets[1], &buf_parent, sizeof(buf_parent)));828	ASSERT_EQ('a', buf_parent);829	EXPECT_LE(0, close(unnamed_sockets[1]));830 831	/* Reads from pathname sockets. */832	data_socket = accept(stream_pathname_socket, NULL, NULL);833	ASSERT_LE(0, data_socket);834	ASSERT_EQ(1, read(data_socket, &buf_parent, sizeof(buf_parent)));835	ASSERT_EQ('b', buf_parent);836	EXPECT_EQ(0, close(data_socket));837	EXPECT_EQ(0, close(stream_pathname_socket));838 839	ASSERT_EQ(1,840		  read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));841	ASSERT_EQ('c', buf_parent);842	ASSERT_EQ(1,843		  read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent)));844	ASSERT_EQ('d', buf_parent);845	EXPECT_EQ(0, close(dgram_pathname_socket));846 847	if (variant->domain != SCOPE_SANDBOX) {848		/* Reads from abstract sockets if allowed to send. */849		data_socket = accept(stream_abstract_socket, NULL, NULL);850		ASSERT_LE(0, data_socket);851		ASSERT_EQ(1,852			  read(data_socket, &buf_parent, sizeof(buf_parent)));853		ASSERT_EQ('e', buf_parent);854		EXPECT_EQ(0, close(data_socket));855 856		ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent,857				  sizeof(buf_parent)));858		ASSERT_EQ('f', buf_parent);859		ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent,860				  sizeof(buf_parent)));861		ASSERT_EQ('g', buf_parent);862	}863 864	/* Waits for all abstract socket tests. */865	ASSERT_EQ(child, waitpid(child, &status, 0));866	EXPECT_EQ(0, close(stream_abstract_socket));867	EXPECT_EQ(0, close(dgram_abstract_socket));868 869	if (WIFSIGNALED(status) || !WIFEXITED(status) ||870	    WEXITSTATUS(status) != EXIT_SUCCESS)871		_metadata->exit_code = KSFT_FAIL;872}873 874TEST(datagram_sockets)875{876	struct service_fixture connected_addr, non_connected_addr;877	int server_conn_socket, server_unconn_socket;878	int pipe_parent[2], pipe_child[2];879	int status;880	char buf;881	pid_t child;882 883	drop_caps(_metadata);884	memset(&connected_addr, 0, sizeof(connected_addr));885	set_unix_address(&connected_addr, 0);886	memset(&non_connected_addr, 0, sizeof(non_connected_addr));887	set_unix_address(&non_connected_addr, 1);888 889	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));890	ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));891 892	child = fork();893	ASSERT_LE(0, child);894	if (child == 0) {895		int client_conn_socket, client_unconn_socket;896 897		EXPECT_EQ(0, close(pipe_parent[1]));898		EXPECT_EQ(0, close(pipe_child[0]));899 900		client_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);901		client_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);902		ASSERT_LE(0, client_conn_socket);903		ASSERT_LE(0, client_unconn_socket);904 905		/* Waits for parent to listen. */906		ASSERT_EQ(1, read(pipe_parent[0], &buf, 1));907		ASSERT_EQ(0,908			  connect(client_conn_socket, &connected_addr.unix_addr,909				  connected_addr.unix_addr_len));910 911		/*912		 * Both connected and non-connected sockets can send data when913		 * the domain is not scoped.914		 */915		ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0));916		ASSERT_EQ(1, sendto(client_unconn_socket, ".", 1, 0,917				    &non_connected_addr.unix_addr,918				    non_connected_addr.unix_addr_len));919		ASSERT_EQ(1, write(pipe_child[1], ".", 1));920 921		/* Scopes the domain. */922		create_scoped_domain(_metadata,923				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);924 925		/*926		 * Connected socket sends data to the receiver, but the927		 * non-connected socket must fail to send data.928		 */929		ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0));930		ASSERT_EQ(-1, sendto(client_unconn_socket, ".", 1, 0,931				     &non_connected_addr.unix_addr,932				     non_connected_addr.unix_addr_len));933		ASSERT_EQ(EPERM, errno);934		ASSERT_EQ(1, write(pipe_child[1], ".", 1));935 936		EXPECT_EQ(0, close(client_conn_socket));937		EXPECT_EQ(0, close(client_unconn_socket));938		_exit(_metadata->exit_code);939		return;940	}941	EXPECT_EQ(0, close(pipe_parent[0]));942	EXPECT_EQ(0, close(pipe_child[1]));943 944	server_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);945	server_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0);946	ASSERT_LE(0, server_conn_socket);947	ASSERT_LE(0, server_unconn_socket);948 949	ASSERT_EQ(0, bind(server_conn_socket, &connected_addr.unix_addr,950			  connected_addr.unix_addr_len));951	ASSERT_EQ(0, bind(server_unconn_socket, &non_connected_addr.unix_addr,952			  non_connected_addr.unix_addr_len));953	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));954 955	/* Waits for child to test. */956	ASSERT_EQ(1, read(pipe_child[0], &buf, 1));957	ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0));958	ASSERT_EQ(1, recv(server_unconn_socket, &buf, 1, 0));959 960	/*961	 * Connected datagram socket will receive data, but962	 * non-connected datagram socket does not receive data.963	 */964	ASSERT_EQ(1, read(pipe_child[0], &buf, 1));965	ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0));966 967	/* Waits for all tests to finish. */968	ASSERT_EQ(child, waitpid(child, &status, 0));969	EXPECT_EQ(0, close(server_conn_socket));970	EXPECT_EQ(0, close(server_unconn_socket));971 972	if (WIFSIGNALED(status) || !WIFEXITED(status) ||973	    WEXITSTATUS(status) != EXIT_SUCCESS)974		_metadata->exit_code = KSFT_FAIL;975}976 977TEST(self_connect)978{979	struct service_fixture connected_addr, non_connected_addr;980	int connected_socket, non_connected_socket, status;981	pid_t child;982 983	drop_caps(_metadata);984	memset(&connected_addr, 0, sizeof(connected_addr));985	set_unix_address(&connected_addr, 0);986	memset(&non_connected_addr, 0, sizeof(non_connected_addr));987	set_unix_address(&non_connected_addr, 1);988 989	connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0);990	non_connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0);991	ASSERT_LE(0, connected_socket);992	ASSERT_LE(0, non_connected_socket);993 994	ASSERT_EQ(0, bind(connected_socket, &connected_addr.unix_addr,995			  connected_addr.unix_addr_len));996	ASSERT_EQ(0, bind(non_connected_socket, &non_connected_addr.unix_addr,997			  non_connected_addr.unix_addr_len));998 999	child = fork();1000	ASSERT_LE(0, child);1001	if (child == 0) {1002		/* Child's domain is scoped. */1003		create_scoped_domain(_metadata,1004				     LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);1005 1006		/*1007		 * The child inherits the sockets, and cannot connect or1008		 * send data to them.1009		 */1010		ASSERT_EQ(-1,1011			  connect(connected_socket, &connected_addr.unix_addr,1012				  connected_addr.unix_addr_len));1013		ASSERT_EQ(EPERM, errno);1014 1015		ASSERT_EQ(-1, sendto(connected_socket, ".", 1, 0,1016				     &connected_addr.unix_addr,1017				     connected_addr.unix_addr_len));1018		ASSERT_EQ(EPERM, errno);1019 1020		ASSERT_EQ(-1, sendto(non_connected_socket, ".", 1, 0,1021				     &non_connected_addr.unix_addr,1022				     non_connected_addr.unix_addr_len));1023		ASSERT_EQ(EPERM, errno);1024 1025		EXPECT_EQ(0, close(connected_socket));1026		EXPECT_EQ(0, close(non_connected_socket));1027		_exit(_metadata->exit_code);1028		return;1029	}1030 1031	/* Waits for all tests to finish. */1032	ASSERT_EQ(child, waitpid(child, &status, 0));1033	EXPECT_EQ(0, close(connected_socket));1034	EXPECT_EQ(0, close(non_connected_socket));1035 1036	if (WIFSIGNALED(status) || !WIFEXITED(status) ||1037	    WEXITSTATUS(status) != EXIT_SUCCESS)1038		_metadata->exit_code = KSFT_FAIL;1039}1040 1041TEST_HARNESS_MAIN1042