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