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