xref: /linux/tools/testing/selftests/landlock/audit_test.c (revision 22c55fb9eb92395d999b8404d73e58540d11bdd8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Landlock tests - Audit
4  *
5  * Copyright © 2024-2025 Microsoft Corporation
6  */
7 
8 #define _GNU_SOURCE
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <limits.h>
12 #include <linux/landlock.h>
13 #include <pthread.h>
14 #include <stdlib.h>
15 #include <sys/mount.h>
16 #include <sys/prctl.h>
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20 
21 #include "audit.h"
22 #include "common.h"
23 
24 static int matches_log_signal(struct __test_metadata *const _metadata,
25 			      int audit_fd, const pid_t opid, __u64 *domain_id)
26 {
27 	static const char log_template[] = REGEX_LANDLOCK_PREFIX
28 		" blockers=scope\\.signal opid=%d ocomm=\"audit_test\"$";
29 	char log_match[sizeof(log_template) + 10];
30 	int log_match_len;
31 
32 	log_match_len =
33 		snprintf(log_match, sizeof(log_match), log_template, opid);
34 	if (log_match_len > sizeof(log_match))
35 		return -E2BIG;
36 
37 	return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
38 				  domain_id);
39 }
40 
41 FIXTURE(audit)
42 {
43 	struct audit_filter audit_filter;
44 	int audit_fd;
45 };
46 
47 FIXTURE_SETUP(audit)
48 {
49 	disable_caps(_metadata);
50 	set_cap(_metadata, CAP_AUDIT_CONTROL);
51 	self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
52 	EXPECT_LE(0, self->audit_fd)
53 	{
54 		const char *error_msg;
55 
56 		/* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
57 		if (self->audit_fd == -EEXIST)
58 			error_msg = "socket already in use (e.g. auditd)";
59 		else
60 			error_msg = strerror(-self->audit_fd);
61 		TH_LOG("Failed to initialize audit: %s", error_msg);
62 	}
63 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
64 }
65 
66 FIXTURE_TEARDOWN(audit)
67 {
68 	set_cap(_metadata, CAP_AUDIT_CONTROL);
69 	EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter));
70 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
71 }
72 
73 TEST_F(audit, layers)
74 {
75 	const struct landlock_ruleset_attr ruleset_attr = {
76 		.scoped = LANDLOCK_SCOPE_SIGNAL,
77 	};
78 	int status, ruleset_fd, i;
79 	__u64(*domain_stack)[16];
80 	__u64 prev_dom = 3;
81 	pid_t child;
82 
83 	domain_stack = mmap(NULL, sizeof(*domain_stack), PROT_READ | PROT_WRITE,
84 			    MAP_SHARED | MAP_ANONYMOUS, -1, 0);
85 	ASSERT_NE(MAP_FAILED, domain_stack);
86 	memset(domain_stack, 0, sizeof(*domain_stack));
87 
88 	ruleset_fd =
89 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
90 	ASSERT_LE(0, ruleset_fd);
91 	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
92 
93 	child = fork();
94 	ASSERT_LE(0, child);
95 	if (child == 0) {
96 		for (i = 0; i < ARRAY_SIZE(*domain_stack); i++) {
97 			__u64 denial_dom = 1;
98 			__u64 allocated_dom = 2;
99 
100 			EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
101 
102 			/* Creates a denial to get the domain ID. */
103 			EXPECT_EQ(-1, kill(getppid(), 0));
104 			EXPECT_EQ(EPERM, errno);
105 			EXPECT_EQ(0,
106 				  matches_log_signal(_metadata, self->audit_fd,
107 						     getppid(), &denial_dom));
108 			EXPECT_EQ(0, matches_log_domain_allocated(
109 					     self->audit_fd, getpid(),
110 					     &allocated_dom));
111 			EXPECT_NE(denial_dom, 1);
112 			EXPECT_NE(denial_dom, 0);
113 			EXPECT_EQ(denial_dom, allocated_dom);
114 
115 			/* Checks that the new domain is younger than the previous one. */
116 			EXPECT_GT(allocated_dom, prev_dom);
117 			prev_dom = allocated_dom;
118 			(*domain_stack)[i] = allocated_dom;
119 		}
120 
121 		/* Checks that we reached the maximum number of layers. */
122 		EXPECT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
123 		EXPECT_EQ(E2BIG, errno);
124 
125 		/* Updates filter rules to match the drop record. */
126 		set_cap(_metadata, CAP_AUDIT_CONTROL);
127 		EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
128 		EXPECT_EQ(0,
129 			  audit_filter_exe(self->audit_fd, &self->audit_filter,
130 					   AUDIT_DEL_RULE));
131 		clear_cap(_metadata, CAP_AUDIT_CONTROL);
132 
133 		_exit(_metadata->exit_code);
134 		return;
135 	}
136 
137 	ASSERT_EQ(child, waitpid(child, &status, 0));
138 	if (WIFSIGNALED(status) || !WIFEXITED(status) ||
139 	    WEXITSTATUS(status) != EXIT_SUCCESS)
140 		_metadata->exit_code = KSFT_FAIL;
141 
142 	/* Purges log from deallocated domains. */
143 	EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
144 				&audit_tv_dom_drop, sizeof(audit_tv_dom_drop)));
145 	for (i = ARRAY_SIZE(*domain_stack) - 1; i >= 0; i--) {
146 		__u64 deallocated_dom = 2;
147 
148 		EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 1,
149 							    &deallocated_dom));
150 		EXPECT_EQ((*domain_stack)[i], deallocated_dom)
151 		{
152 			TH_LOG("Failed to match domain %llx (#%d)",
153 			       (*domain_stack)[i], i);
154 		}
155 	}
156 	EXPECT_EQ(0, munmap(domain_stack, sizeof(*domain_stack)));
157 	EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
158 				&audit_tv_default, sizeof(audit_tv_default)));
159 	EXPECT_EQ(0, close(ruleset_fd));
160 }
161 
162 struct thread_data {
163 	pid_t parent_pid;
164 	int ruleset_fd, pipe_child, pipe_parent;
165 };
166 
167 static void *thread_audit_test(void *arg)
168 {
169 	const struct thread_data *data = (struct thread_data *)arg;
170 	uintptr_t err = 0;
171 	char buffer;
172 
173 	/* TGID and TID are different for a second thread. */
174 	if (getpid() == gettid()) {
175 		err = 1;
176 		goto out;
177 	}
178 
179 	if (landlock_restrict_self(data->ruleset_fd, 0)) {
180 		err = 2;
181 		goto out;
182 	}
183 
184 	if (close(data->ruleset_fd)) {
185 		err = 3;
186 		goto out;
187 	}
188 
189 	/* Creates a denial to get the domain ID. */
190 	if (kill(data->parent_pid, 0) != -1) {
191 		err = 4;
192 		goto out;
193 	}
194 
195 	if (EPERM != errno) {
196 		err = 5;
197 		goto out;
198 	}
199 
200 	/* Signals the parent to read denial logs. */
201 	if (write(data->pipe_child, ".", 1) != 1) {
202 		err = 6;
203 		goto out;
204 	}
205 
206 	/* Waits for the parent to update audit filters. */
207 	if (read(data->pipe_parent, &buffer, 1) != 1) {
208 		err = 7;
209 		goto out;
210 	}
211 
212 out:
213 	close(data->pipe_child);
214 	close(data->pipe_parent);
215 	return (void *)err;
216 }
217 
218 /* Checks that the PID tied to a domain is not a TID but the TGID. */
219 TEST_F(audit, thread)
220 {
221 	const struct landlock_ruleset_attr ruleset_attr = {
222 		.scoped = LANDLOCK_SCOPE_SIGNAL,
223 	};
224 	__u64 denial_dom = 1;
225 	__u64 allocated_dom = 2;
226 	__u64 deallocated_dom = 3;
227 	pthread_t thread;
228 	int pipe_child[2], pipe_parent[2];
229 	char buffer;
230 	struct thread_data child_data;
231 
232 	child_data.parent_pid = getppid();
233 	ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC));
234 	child_data.pipe_child = pipe_child[1];
235 	ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC));
236 	child_data.pipe_parent = pipe_parent[0];
237 	child_data.ruleset_fd =
238 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
239 	ASSERT_LE(0, child_data.ruleset_fd);
240 
241 	/* TGID and TID are the same for the initial thread . */
242 	EXPECT_EQ(getpid(), gettid());
243 	EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
244 	ASSERT_EQ(0, pthread_create(&thread, NULL, thread_audit_test,
245 				    &child_data));
246 
247 	/* Waits for the child to generate a denial. */
248 	ASSERT_EQ(1, read(pipe_child[0], &buffer, 1));
249 	EXPECT_EQ(0, close(pipe_child[0]));
250 
251 	/* Matches the signal log to get the domain ID. */
252 	EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
253 					child_data.parent_pid, &denial_dom));
254 	EXPECT_NE(denial_dom, 1);
255 	EXPECT_NE(denial_dom, 0);
256 
257 	EXPECT_EQ(0, matches_log_domain_allocated(self->audit_fd, getpid(),
258 						  &allocated_dom));
259 	EXPECT_EQ(denial_dom, allocated_dom);
260 
261 	/* Updates filter rules to match the drop record. */
262 	set_cap(_metadata, CAP_AUDIT_CONTROL);
263 	EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
264 	EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
265 				      AUDIT_DEL_RULE));
266 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
267 
268 	/* Signals the thread to exit, which will generate a domain deallocation. */
269 	ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
270 	EXPECT_EQ(0, close(pipe_parent[1]));
271 	ASSERT_EQ(0, pthread_join(thread, NULL));
272 
273 	EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
274 				&audit_tv_dom_drop, sizeof(audit_tv_dom_drop)));
275 	EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 1,
276 						    &deallocated_dom));
277 	EXPECT_EQ(denial_dom, deallocated_dom);
278 	EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
279 				&audit_tv_default, sizeof(audit_tv_default)));
280 }
281 
282 FIXTURE(audit_flags)
283 {
284 	struct audit_filter audit_filter;
285 	int audit_fd;
286 	__u64 *domain_id;
287 };
288 
289 FIXTURE_VARIANT(audit_flags)
290 {
291 	const int restrict_flags;
292 };
293 
294 /* clang-format off */
295 FIXTURE_VARIANT_ADD(audit_flags, default) {
296 	/* clang-format on */
297 	.restrict_flags = 0,
298 };
299 
300 /* clang-format off */
301 FIXTURE_VARIANT_ADD(audit_flags, same_exec_off) {
302 	/* clang-format on */
303 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF,
304 };
305 
306 /* clang-format off */
307 FIXTURE_VARIANT_ADD(audit_flags, subdomains_off) {
308 	/* clang-format on */
309 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF,
310 };
311 
312 /* clang-format off */
313 FIXTURE_VARIANT_ADD(audit_flags, cross_exec_on) {
314 	/* clang-format on */
315 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
316 };
317 
318 FIXTURE_SETUP(audit_flags)
319 {
320 	disable_caps(_metadata);
321 	set_cap(_metadata, CAP_AUDIT_CONTROL);
322 	self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
323 	EXPECT_LE(0, self->audit_fd)
324 	{
325 		const char *error_msg;
326 
327 		/* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
328 		if (self->audit_fd == -EEXIST)
329 			error_msg = "socket already in use (e.g. auditd)";
330 		else
331 			error_msg = strerror(-self->audit_fd);
332 		TH_LOG("Failed to initialize audit: %s", error_msg);
333 	}
334 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
335 
336 	self->domain_id = mmap(NULL, sizeof(*self->domain_id),
337 			       PROT_READ | PROT_WRITE,
338 			       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
339 	ASSERT_NE(MAP_FAILED, self->domain_id);
340 	/* Domain IDs are greater or equal to 2^32. */
341 	*self->domain_id = 1;
342 }
343 
344 FIXTURE_TEARDOWN(audit_flags)
345 {
346 	EXPECT_EQ(0, munmap(self->domain_id, sizeof(*self->domain_id)));
347 
348 	set_cap(_metadata, CAP_AUDIT_CONTROL);
349 	EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter));
350 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
351 }
352 
353 TEST_F(audit_flags, signal)
354 {
355 	int status;
356 	pid_t child;
357 	struct audit_records records;
358 	__u64 deallocated_dom = 2;
359 
360 	child = fork();
361 	ASSERT_LE(0, child);
362 	if (child == 0) {
363 		const struct landlock_ruleset_attr ruleset_attr = {
364 			.scoped = LANDLOCK_SCOPE_SIGNAL,
365 		};
366 		int ruleset_fd;
367 
368 		/* Add filesystem restrictions. */
369 		ruleset_fd = landlock_create_ruleset(&ruleset_attr,
370 						     sizeof(ruleset_attr), 0);
371 		ASSERT_LE(0, ruleset_fd);
372 		EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
373 		ASSERT_EQ(0, landlock_restrict_self(ruleset_fd,
374 						    variant->restrict_flags));
375 		EXPECT_EQ(0, close(ruleset_fd));
376 
377 		/* First signal checks to test log entries. */
378 		EXPECT_EQ(-1, kill(getppid(), 0));
379 		EXPECT_EQ(EPERM, errno);
380 
381 		if (variant->restrict_flags &
382 		    LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
383 			EXPECT_EQ(-EAGAIN, matches_log_signal(
384 						   _metadata, self->audit_fd,
385 						   getppid(), self->domain_id));
386 			EXPECT_EQ(*self->domain_id, 1);
387 		} else {
388 			__u64 allocated_dom = 3;
389 
390 			EXPECT_EQ(0, matches_log_signal(
391 					     _metadata, self->audit_fd,
392 					     getppid(), self->domain_id));
393 
394 			/* Checks domain information records. */
395 			EXPECT_EQ(0, matches_log_domain_allocated(
396 					     self->audit_fd, getpid(),
397 					     &allocated_dom));
398 			EXPECT_NE(*self->domain_id, 1);
399 			EXPECT_NE(*self->domain_id, 0);
400 			EXPECT_EQ(*self->domain_id, allocated_dom);
401 		}
402 
403 		/* Second signal checks to test audit_count_records(). */
404 		EXPECT_EQ(-1, kill(getppid(), 0));
405 		EXPECT_EQ(EPERM, errno);
406 
407 		/* Makes sure there is no superfluous logged records. */
408 		EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
409 		if (variant->restrict_flags &
410 		    LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
411 			EXPECT_EQ(0, records.access);
412 		} else {
413 			EXPECT_EQ(1, records.access);
414 		}
415 		EXPECT_EQ(0, records.domain);
416 
417 		/* Updates filter rules to match the drop record. */
418 		set_cap(_metadata, CAP_AUDIT_CONTROL);
419 		EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE));
420 		EXPECT_EQ(0,
421 			  audit_filter_exe(self->audit_fd, &self->audit_filter,
422 					   AUDIT_DEL_RULE));
423 		clear_cap(_metadata, CAP_AUDIT_CONTROL);
424 
425 		_exit(_metadata->exit_code);
426 		return;
427 	}
428 
429 	ASSERT_EQ(child, waitpid(child, &status, 0));
430 	if (WIFSIGNALED(status) || !WIFEXITED(status) ||
431 	    WEXITSTATUS(status) != EXIT_SUCCESS)
432 		_metadata->exit_code = KSFT_FAIL;
433 
434 	if (variant->restrict_flags &
435 	    LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) {
436 		EXPECT_EQ(-EAGAIN,
437 			  matches_log_domain_deallocated(self->audit_fd, 0,
438 							 &deallocated_dom));
439 		EXPECT_EQ(deallocated_dom, 2);
440 	} else {
441 		EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
442 					&audit_tv_dom_drop,
443 					sizeof(audit_tv_dom_drop)));
444 		EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 2,
445 							    &deallocated_dom));
446 		EXPECT_NE(deallocated_dom, 2);
447 		EXPECT_NE(deallocated_dom, 0);
448 		EXPECT_EQ(deallocated_dom, *self->domain_id);
449 		EXPECT_EQ(0, setsockopt(self->audit_fd, SOL_SOCKET, SO_RCVTIMEO,
450 					&audit_tv_default,
451 					sizeof(audit_tv_default)));
452 	}
453 }
454 
455 static int matches_log_fs_read_root(int audit_fd)
456 {
457 	return audit_match_record(
458 		audit_fd, AUDIT_LANDLOCK_ACCESS,
459 		REGEX_LANDLOCK_PREFIX
460 		" blockers=fs\\.read_dir path=\"/\" dev=\"[^\"]\\+\" ino=[0-9]\\+$",
461 		NULL);
462 }
463 
464 FIXTURE(audit_exec)
465 {
466 	struct audit_filter audit_filter;
467 	int audit_fd;
468 };
469 
470 FIXTURE_VARIANT(audit_exec)
471 {
472 	const int restrict_flags;
473 };
474 
475 /* clang-format off */
476 FIXTURE_VARIANT_ADD(audit_exec, default) {
477 	/* clang-format on */
478 	.restrict_flags = 0,
479 };
480 
481 /* clang-format off */
482 FIXTURE_VARIANT_ADD(audit_exec, same_exec_off) {
483 	/* clang-format on */
484 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF,
485 };
486 
487 /* clang-format off */
488 FIXTURE_VARIANT_ADD(audit_exec, subdomains_off) {
489 	/* clang-format on */
490 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF,
491 };
492 
493 /* clang-format off */
494 FIXTURE_VARIANT_ADD(audit_exec, cross_exec_on) {
495 	/* clang-format on */
496 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
497 };
498 
499 /* clang-format off */
500 FIXTURE_VARIANT_ADD(audit_exec, subdomains_off_and_cross_exec_on) {
501 	/* clang-format on */
502 	.restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF |
503 			  LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON,
504 };
505 
506 FIXTURE_SETUP(audit_exec)
507 {
508 	disable_caps(_metadata);
509 	set_cap(_metadata, CAP_AUDIT_CONTROL);
510 
511 	self->audit_fd = audit_init();
512 	EXPECT_LE(0, self->audit_fd)
513 	{
514 		const char *error_msg;
515 
516 		/* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */
517 		if (self->audit_fd == -EEXIST)
518 			error_msg = "socket already in use (e.g. auditd)";
519 		else
520 			error_msg = strerror(-self->audit_fd);
521 		TH_LOG("Failed to initialize audit: %s", error_msg);
522 	}
523 
524 	/* Applies test filter for the bin_wait_pipe_sandbox program. */
525 	EXPECT_EQ(0, audit_init_filter_exe(&self->audit_filter,
526 					   bin_wait_pipe_sandbox));
527 	EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
528 				      AUDIT_ADD_RULE));
529 
530 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
531 }
532 
533 FIXTURE_TEARDOWN(audit_exec)
534 {
535 	set_cap(_metadata, CAP_AUDIT_CONTROL);
536 	EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter,
537 				      AUDIT_DEL_RULE));
538 	clear_cap(_metadata, CAP_AUDIT_CONTROL);
539 	EXPECT_EQ(0, close(self->audit_fd));
540 }
541 
542 TEST_F(audit_exec, signal_and_open)
543 {
544 	struct audit_records records;
545 	int pipe_child[2], pipe_parent[2];
546 	char buf_parent;
547 	pid_t child;
548 	int status;
549 
550 	ASSERT_EQ(0, pipe2(pipe_child, 0));
551 	ASSERT_EQ(0, pipe2(pipe_parent, 0));
552 
553 	child = fork();
554 	ASSERT_LE(0, child);
555 	if (child == 0) {
556 		const struct landlock_ruleset_attr layer1 = {
557 			.scoped = LANDLOCK_SCOPE_SIGNAL,
558 		};
559 		char pipe_child_str[12], pipe_parent_str[12];
560 		char *const argv[] = { (char *)bin_wait_pipe_sandbox,
561 				       pipe_child_str, pipe_parent_str, NULL };
562 		int ruleset_fd;
563 
564 		/* Passes the pipe FDs to the executed binary. */
565 		EXPECT_EQ(0, close(pipe_child[0]));
566 		EXPECT_EQ(0, close(pipe_parent[1]));
567 		snprintf(pipe_child_str, sizeof(pipe_child_str), "%d",
568 			 pipe_child[1]);
569 		snprintf(pipe_parent_str, sizeof(pipe_parent_str), "%d",
570 			 pipe_parent[0]);
571 
572 		ruleset_fd =
573 			landlock_create_ruleset(&layer1, sizeof(layer1), 0);
574 		if (ruleset_fd < 0) {
575 			perror("Failed to create a ruleset");
576 			_exit(1);
577 		}
578 		prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
579 		if (landlock_restrict_self(ruleset_fd,
580 					   variant->restrict_flags)) {
581 			perror("Failed to restrict self");
582 			_exit(1);
583 		}
584 		close(ruleset_fd);
585 
586 		ASSERT_EQ(0, execve(argv[0], argv, NULL))
587 		{
588 			TH_LOG("Failed to execute \"%s\": %s", argv[0],
589 			       strerror(errno));
590 		};
591 		_exit(1);
592 		return;
593 	}
594 
595 	EXPECT_EQ(0, close(pipe_child[1]));
596 	EXPECT_EQ(0, close(pipe_parent[0]));
597 
598 	/* Waits for the child. */
599 	EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
600 
601 	/* Tests that there was no denial until now. */
602 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
603 	EXPECT_EQ(0, records.access);
604 	EXPECT_EQ(0, records.domain);
605 
606 	/*
607 	 * Wait for the child to do a first denied action by layer1 and
608 	 * sandbox itself with layer2.
609 	 */
610 	EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
611 	EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
612 
613 	/* Tests that the audit record only matches the child. */
614 	if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) {
615 		/* Matches the current domain. */
616 		EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
617 						getpid(), NULL));
618 	}
619 
620 	/* Checks that we didn't miss anything. */
621 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
622 	EXPECT_EQ(0, records.access);
623 
624 	/*
625 	 * Wait for the child to do a second denied action by layer1 and
626 	 * layer2, and sandbox itself with layer3.
627 	 */
628 	EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
629 	EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
630 
631 	/* Tests that the audit record only matches the child. */
632 	if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) {
633 		/* Matches the current domain. */
634 		EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
635 						getpid(), NULL));
636 	}
637 
638 	if (!(variant->restrict_flags &
639 	      LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) {
640 		/* Matches the child domain. */
641 		EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd));
642 	}
643 
644 	/* Checks that we didn't miss anything. */
645 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
646 	EXPECT_EQ(0, records.access);
647 
648 	/* Waits for the child to terminate. */
649 	EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
650 	ASSERT_EQ(child, waitpid(child, &status, 0));
651 	ASSERT_EQ(1, WIFEXITED(status));
652 	ASSERT_EQ(0, WEXITSTATUS(status));
653 
654 	/* Tests that the audit record only matches the child. */
655 	if (!(variant->restrict_flags &
656 	      LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) {
657 		/*
658 		 * Matches the child domains, which tests that the
659 		 * llcred->domain_exec bitmask is correctly updated with a new
660 		 * domain.
661 		 */
662 		EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd));
663 		EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd,
664 						getpid(), NULL));
665 	}
666 
667 	/* Checks that we didn't miss anything. */
668 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
669 	EXPECT_EQ(0, records.access);
670 }
671 
672 TEST_HARNESS_MAIN
673