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 /* 143 * Purges log from deallocated domains. Records arrive in LIFO order 144 * (innermost domain first) because landlock_put_hierarchy() walks the 145 * chain sequentially in a single kworker context. 146 */ 147 for (i = ARRAY_SIZE(*domain_stack) - 1; i >= 0; i--) { 148 __u64 deallocated_dom = 2; 149 150 EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 1, 151 (*domain_stack)[i], 152 &deallocated_dom)); 153 EXPECT_EQ((*domain_stack)[i], deallocated_dom) 154 { 155 TH_LOG("Failed to match domain %llx (#%d)", 156 (unsigned long long)(*domain_stack)[i], i); 157 } 158 } 159 EXPECT_EQ(0, munmap(domain_stack, sizeof(*domain_stack))); 160 EXPECT_EQ(0, close(ruleset_fd)); 161 } 162 163 struct thread_data { 164 pid_t parent_pid; 165 int ruleset_fd, pipe_child, pipe_parent; 166 bool mute_subdomains; 167 }; 168 169 static void *thread_audit_test(void *arg) 170 { 171 const struct thread_data *data = (struct thread_data *)arg; 172 uintptr_t err = 0; 173 char buffer; 174 175 /* TGID and TID are different for a second thread. */ 176 if (getpid() == gettid()) { 177 err = 1; 178 goto out; 179 } 180 181 if (landlock_restrict_self(data->ruleset_fd, 0)) { 182 err = 2; 183 goto out; 184 } 185 186 if (close(data->ruleset_fd)) { 187 err = 3; 188 goto out; 189 } 190 191 /* Creates a denial to get the domain ID. */ 192 if (kill(data->parent_pid, 0) != -1) { 193 err = 4; 194 goto out; 195 } 196 197 if (EPERM != errno) { 198 err = 5; 199 goto out; 200 } 201 202 /* Signals the parent to read denial logs. */ 203 if (write(data->pipe_child, ".", 1) != 1) { 204 err = 6; 205 goto out; 206 } 207 208 /* Waits for the parent to update audit filters. */ 209 if (read(data->pipe_parent, &buffer, 1) != 1) { 210 err = 7; 211 goto out; 212 } 213 214 out: 215 close(data->pipe_child); 216 close(data->pipe_parent); 217 return (void *)err; 218 } 219 220 /* Checks that the PID tied to a domain is not a TID but the TGID. */ 221 TEST_F(audit, thread) 222 { 223 const struct landlock_ruleset_attr ruleset_attr = { 224 .scoped = LANDLOCK_SCOPE_SIGNAL, 225 }; 226 __u64 denial_dom = 1; 227 __u64 allocated_dom = 2; 228 __u64 deallocated_dom = 3; 229 pthread_t thread; 230 int pipe_child[2], pipe_parent[2]; 231 char buffer; 232 struct thread_data child_data; 233 234 child_data.parent_pid = getppid(); 235 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 236 child_data.pipe_child = pipe_child[1]; 237 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 238 child_data.pipe_parent = pipe_parent[0]; 239 child_data.ruleset_fd = 240 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 241 ASSERT_LE(0, child_data.ruleset_fd); 242 243 /* TGID and TID are the same for the initial thread . */ 244 EXPECT_EQ(getpid(), gettid()); 245 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 246 ASSERT_EQ(0, pthread_create(&thread, NULL, thread_audit_test, 247 &child_data)); 248 249 /* Waits for the child to generate a denial. */ 250 ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); 251 EXPECT_EQ(0, close(pipe_child[0])); 252 253 /* Matches the signal log to get the domain ID. */ 254 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 255 child_data.parent_pid, &denial_dom)); 256 EXPECT_NE(denial_dom, 1); 257 EXPECT_NE(denial_dom, 0); 258 259 EXPECT_EQ(0, matches_log_domain_allocated(self->audit_fd, getpid(), 260 &allocated_dom)); 261 EXPECT_EQ(denial_dom, allocated_dom); 262 263 /* Updates filter rules to match the drop record. */ 264 set_cap(_metadata, CAP_AUDIT_CONTROL); 265 EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE)); 266 EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter, 267 AUDIT_DEL_RULE)); 268 clear_cap(_metadata, CAP_AUDIT_CONTROL); 269 270 /* Signals the thread to exit, which will generate a domain deallocation. */ 271 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 272 EXPECT_EQ(0, close(pipe_parent[1])); 273 ASSERT_EQ(0, pthread_join(thread, NULL)); 274 275 EXPECT_EQ(0, matches_log_domain_deallocated( 276 self->audit_fd, 1, denial_dom, &deallocated_dom)); 277 EXPECT_EQ(denial_dom, deallocated_dom); 278 } 279 280 /* 281 * Verifies that log_subdomains_off set via the ruleset_fd=-1 path (without 282 * creating a domain) is inherited by children across fork(). This exercises 283 * the hook_cred_transfer() fix: the Landlock credential blob must be copied 284 * even when the source credential has no domain. 285 * 286 * Phase 1 (baseline): a child without muting creates a domain and triggers a 287 * denial that IS logged. 288 * 289 * Phase 2 (after muting): the parent mutes subdomain logs, forks another child 290 * who creates a domain and triggers a denial that is NOT logged. 291 */ 292 TEST_F(audit, log_subdomains_off_fork) 293 { 294 const struct landlock_ruleset_attr ruleset_attr = { 295 .scoped = LANDLOCK_SCOPE_SIGNAL, 296 }; 297 struct audit_records records; 298 int ruleset_fd, status; 299 pid_t child; 300 301 ruleset_fd = 302 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 303 ASSERT_LE(0, ruleset_fd); 304 305 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 306 307 /* 308 * Phase 1: forks a child that creates a domain and triggers a denial 309 * before any muting. This proves the audit path works. 310 */ 311 child = fork(); 312 ASSERT_LE(0, child); 313 if (child == 0) { 314 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)); 315 ASSERT_EQ(-1, kill(getppid(), 0)); 316 ASSERT_EQ(EPERM, errno); 317 _exit(0); 318 return; 319 } 320 321 ASSERT_EQ(child, waitpid(child, &status, 0)); 322 ASSERT_EQ(true, WIFEXITED(status)); 323 ASSERT_EQ(0, WEXITSTATUS(status)); 324 325 /* The denial must be logged (baseline). */ 326 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, getpid(), 327 NULL)); 328 329 /* Drains any remaining records (e.g. domain allocation). */ 330 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 331 332 /* 333 * Mutes subdomain logs without creating a domain. The parent's 334 * credential has domain=NULL and log_subdomains_off=1. 335 */ 336 ASSERT_EQ(0, landlock_restrict_self( 337 -1, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)); 338 339 /* 340 * Phase 2: forks a child that creates a domain and triggers a denial. 341 * Because log_subdomains_off was inherited via fork(), the child's 342 * domain has log_status=LANDLOCK_LOG_DISABLED. 343 */ 344 child = fork(); 345 ASSERT_LE(0, child); 346 if (child == 0) { 347 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)); 348 ASSERT_EQ(-1, kill(getppid(), 0)); 349 ASSERT_EQ(EPERM, errno); 350 _exit(0); 351 return; 352 } 353 354 ASSERT_EQ(child, waitpid(child, &status, 0)); 355 ASSERT_EQ(true, WIFEXITED(status)); 356 ASSERT_EQ(0, WEXITSTATUS(status)); 357 358 /* No denial record should appear. */ 359 EXPECT_EQ(-EAGAIN, matches_log_signal(_metadata, self->audit_fd, 360 getpid(), NULL)); 361 362 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 363 EXPECT_EQ(0, records.access); 364 365 EXPECT_EQ(0, close(ruleset_fd)); 366 } 367 368 /* 369 * Thread function: runs two rounds of (create domain, trigger denial, signal 370 * back), waiting for the main thread before each round. When mute_subdomains 371 * is set, phase 1 also mutes subdomain logs via the fd=-1 path before creating 372 * the domain. The ruleset_fd is kept open across both rounds so each 373 * restrict_self call stacks a new domain layer. 374 */ 375 static void *thread_sandbox_deny_twice(void *arg) 376 { 377 const struct thread_data *data = (struct thread_data *)arg; 378 uintptr_t err = 0; 379 char buffer; 380 381 /* Phase 1: optionally mutes, creates a domain, and triggers a denial. */ 382 if (read(data->pipe_parent, &buffer, 1) != 1) { 383 err = 1; 384 goto out; 385 } 386 387 if (data->mute_subdomains && 388 landlock_restrict_self(-1, 389 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) { 390 err = 2; 391 goto out; 392 } 393 394 if (landlock_restrict_self(data->ruleset_fd, 0)) { 395 err = 3; 396 goto out; 397 } 398 399 if (kill(data->parent_pid, 0) != -1 || errno != EPERM) { 400 err = 4; 401 goto out; 402 } 403 404 if (write(data->pipe_child, ".", 1) != 1) { 405 err = 5; 406 goto out; 407 } 408 409 /* Phase 2: stacks another domain and triggers a denial. */ 410 if (read(data->pipe_parent, &buffer, 1) != 1) { 411 err = 6; 412 goto out; 413 } 414 415 if (landlock_restrict_self(data->ruleset_fd, 0)) { 416 err = 7; 417 goto out; 418 } 419 420 if (kill(data->parent_pid, 0) != -1 || errno != EPERM) { 421 err = 8; 422 goto out; 423 } 424 425 if (write(data->pipe_child, ".", 1) != 1) { 426 err = 9; 427 goto out; 428 } 429 430 out: 431 close(data->ruleset_fd); 432 close(data->pipe_child); 433 close(data->pipe_parent); 434 return (void *)err; 435 } 436 437 /* 438 * Verifies that LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF with 439 * LANDLOCK_RESTRICT_SELF_TSYNC and ruleset_fd=-1 propagates log_subdomains_off 440 * to a sibling thread, suppressing audit logging on domains it subsequently 441 * creates. 442 * 443 * Phase 1 (before TSYNC) acts as an inline baseline: the sibling creates a 444 * domain and triggers a denial that IS logged. 445 * 446 * Phase 2 (after TSYNC) verifies suppression: the sibling stacks another domain 447 * and triggers a denial that is NOT logged. 448 */ 449 TEST_F(audit, log_subdomains_off_tsync) 450 { 451 const struct landlock_ruleset_attr ruleset_attr = { 452 .scoped = LANDLOCK_SCOPE_SIGNAL, 453 }; 454 struct audit_records records; 455 struct thread_data child_data = {}; 456 int pipe_child[2], pipe_parent[2]; 457 char buffer; 458 pthread_t thread; 459 void *thread_ret; 460 461 child_data.parent_pid = getppid(); 462 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 463 child_data.pipe_child = pipe_child[1]; 464 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 465 child_data.pipe_parent = pipe_parent[0]; 466 child_data.ruleset_fd = 467 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 468 ASSERT_LE(0, child_data.ruleset_fd); 469 470 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 471 472 /* Creates the sibling thread. */ 473 ASSERT_EQ(0, pthread_create(&thread, NULL, thread_sandbox_deny_twice, 474 &child_data)); 475 476 /* 477 * Phase 1: the sibling creates a domain and triggers a denial before 478 * any log muting. This proves the audit path works. 479 */ 480 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 481 ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); 482 483 /* The denial must be logged. */ 484 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 485 child_data.parent_pid, NULL)); 486 487 /* Drains any remaining records (e.g. domain allocation). */ 488 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 489 490 /* 491 * Mutes subdomain logs and propagates to the sibling thread via TSYNC, 492 * without creating a domain. 493 */ 494 ASSERT_EQ(0, landlock_restrict_self( 495 -1, LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF | 496 LANDLOCK_RESTRICT_SELF_TSYNC)); 497 498 /* 499 * Phase 2: the sibling stacks another domain and triggers a denial. 500 * Because log_subdomains_off was propagated via TSYNC, the new domain 501 * has log_status=LANDLOCK_LOG_DISABLED. 502 */ 503 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 504 ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); 505 506 /* No denial record should appear. */ 507 EXPECT_EQ(-EAGAIN, matches_log_signal(_metadata, self->audit_fd, 508 child_data.parent_pid, NULL)); 509 510 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 511 EXPECT_EQ(0, records.access); 512 513 EXPECT_EQ(0, close(pipe_child[0])); 514 EXPECT_EQ(0, close(pipe_parent[1])); 515 ASSERT_EQ(0, pthread_join(thread, &thread_ret)); 516 EXPECT_EQ(NULL, thread_ret); 517 } 518 519 /* 520 * Verifies that LANDLOCK_RESTRICT_SELF_TSYNC without 521 * LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF overrides a sibling thread's 522 * log_subdomains_off, re-enabling audit logging on domains the sibling 523 * subsequently creates. 524 * 525 * Phase 1: the sibling sets log_subdomains_off, creates a muted domain, and 526 * triggers a denial that is NOT logged. 527 * 528 * Phase 2 (after TSYNC without LOG_SUBDOMAINS_OFF): the sibling stacks another 529 * domain and triggers a denial that IS logged, proving the muting was 530 * overridden. 531 */ 532 TEST_F(audit, tsync_override_log_subdomains_off) 533 { 534 const struct landlock_ruleset_attr ruleset_attr = { 535 .scoped = LANDLOCK_SCOPE_SIGNAL, 536 }; 537 struct audit_records records; 538 struct thread_data child_data = {}; 539 int pipe_child[2], pipe_parent[2]; 540 char buffer; 541 pthread_t thread; 542 void *thread_ret; 543 544 child_data.parent_pid = getppid(); 545 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 546 child_data.pipe_child = pipe_child[1]; 547 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 548 child_data.pipe_parent = pipe_parent[0]; 549 child_data.ruleset_fd = 550 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 551 ASSERT_LE(0, child_data.ruleset_fd); 552 553 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 554 555 child_data.mute_subdomains = true; 556 557 /* Creates the sibling thread. */ 558 ASSERT_EQ(0, pthread_create(&thread, NULL, thread_sandbox_deny_twice, 559 &child_data)); 560 561 /* 562 * Phase 1: the sibling mutes subdomain logs, creates a domain, and 563 * triggers a denial. The denial must not be logged. 564 */ 565 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 566 ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); 567 568 EXPECT_EQ(-EAGAIN, matches_log_signal(_metadata, self->audit_fd, 569 child_data.parent_pid, NULL)); 570 571 /* Drains any remaining records. */ 572 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 573 EXPECT_EQ(0, records.access); 574 575 /* 576 * Overrides the sibling's log_subdomains_off by calling TSYNC without 577 * LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF. 578 */ 579 ASSERT_EQ(0, landlock_restrict_self(child_data.ruleset_fd, 580 LANDLOCK_RESTRICT_SELF_TSYNC)); 581 582 /* 583 * Phase 2: the sibling stacks another domain and triggers a denial. 584 * Because TSYNC replaced its log_subdomains_off with 0, the new domain 585 * has log_status=LANDLOCK_LOG_PENDING. 586 */ 587 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 588 ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); 589 590 /* The denial must be logged. */ 591 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 592 child_data.parent_pid, NULL)); 593 594 EXPECT_EQ(0, close(pipe_child[0])); 595 EXPECT_EQ(0, close(pipe_parent[1])); 596 ASSERT_EQ(0, pthread_join(thread, &thread_ret)); 597 EXPECT_EQ(NULL, thread_ret); 598 } 599 600 FIXTURE(audit_flags) 601 { 602 struct audit_filter audit_filter; 603 int audit_fd; 604 __u64 *domain_id; 605 }; 606 607 FIXTURE_VARIANT(audit_flags) 608 { 609 const int restrict_flags; 610 }; 611 612 /* clang-format off */ 613 FIXTURE_VARIANT_ADD(audit_flags, default) { 614 /* clang-format on */ 615 .restrict_flags = 0, 616 }; 617 618 /* clang-format off */ 619 FIXTURE_VARIANT_ADD(audit_flags, same_exec_off) { 620 /* clang-format on */ 621 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF, 622 }; 623 624 /* clang-format off */ 625 FIXTURE_VARIANT_ADD(audit_flags, subdomains_off) { 626 /* clang-format on */ 627 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, 628 }; 629 630 /* clang-format off */ 631 FIXTURE_VARIANT_ADD(audit_flags, cross_exec_on) { 632 /* clang-format on */ 633 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON, 634 }; 635 636 FIXTURE_SETUP(audit_flags) 637 { 638 disable_caps(_metadata); 639 set_cap(_metadata, CAP_AUDIT_CONTROL); 640 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter); 641 EXPECT_LE(0, self->audit_fd) 642 { 643 const char *error_msg; 644 645 /* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */ 646 if (self->audit_fd == -EEXIST) 647 error_msg = "socket already in use (e.g. auditd)"; 648 else 649 error_msg = strerror(-self->audit_fd); 650 TH_LOG("Failed to initialize audit: %s", error_msg); 651 } 652 clear_cap(_metadata, CAP_AUDIT_CONTROL); 653 654 self->domain_id = mmap(NULL, sizeof(*self->domain_id), 655 PROT_READ | PROT_WRITE, 656 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 657 ASSERT_NE(MAP_FAILED, self->domain_id); 658 /* Domain IDs are greater or equal to 2^32. */ 659 *self->domain_id = 1; 660 } 661 662 FIXTURE_TEARDOWN(audit_flags) 663 { 664 EXPECT_EQ(0, munmap(self->domain_id, sizeof(*self->domain_id))); 665 666 set_cap(_metadata, CAP_AUDIT_CONTROL); 667 EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter)); 668 clear_cap(_metadata, CAP_AUDIT_CONTROL); 669 } 670 671 TEST_F(audit_flags, signal) 672 { 673 int status; 674 pid_t child; 675 struct audit_records records; 676 __u64 deallocated_dom = 2; 677 678 child = fork(); 679 ASSERT_LE(0, child); 680 if (child == 0) { 681 const struct landlock_ruleset_attr ruleset_attr = { 682 .scoped = LANDLOCK_SCOPE_SIGNAL, 683 }; 684 int ruleset_fd; 685 686 /* Add filesystem restrictions. */ 687 ruleset_fd = landlock_create_ruleset(&ruleset_attr, 688 sizeof(ruleset_attr), 0); 689 ASSERT_LE(0, ruleset_fd); 690 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 691 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 692 variant->restrict_flags)); 693 EXPECT_EQ(0, close(ruleset_fd)); 694 695 /* First signal checks to test log entries. */ 696 EXPECT_EQ(-1, kill(getppid(), 0)); 697 EXPECT_EQ(EPERM, errno); 698 699 if (variant->restrict_flags & 700 LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) { 701 EXPECT_EQ(-EAGAIN, matches_log_signal( 702 _metadata, self->audit_fd, 703 getppid(), self->domain_id)); 704 EXPECT_EQ(*self->domain_id, 1); 705 } else { 706 __u64 allocated_dom = 3; 707 708 EXPECT_EQ(0, matches_log_signal( 709 _metadata, self->audit_fd, 710 getppid(), self->domain_id)); 711 712 /* Checks domain information records. */ 713 EXPECT_EQ(0, matches_log_domain_allocated( 714 self->audit_fd, getpid(), 715 &allocated_dom)); 716 EXPECT_NE(*self->domain_id, 1); 717 EXPECT_NE(*self->domain_id, 0); 718 EXPECT_EQ(*self->domain_id, allocated_dom); 719 } 720 721 /* Second signal checks to test audit_count_records(). */ 722 EXPECT_EQ(-1, kill(getppid(), 0)); 723 EXPECT_EQ(EPERM, errno); 724 725 /* Makes sure there is no superfluous logged records. */ 726 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 727 if (variant->restrict_flags & 728 LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) { 729 EXPECT_EQ(0, records.access); 730 } else { 731 EXPECT_EQ(1, records.access); 732 } 733 734 /* Updates filter rules to match the drop record. */ 735 set_cap(_metadata, CAP_AUDIT_CONTROL); 736 EXPECT_EQ(0, audit_filter_drop(self->audit_fd, AUDIT_ADD_RULE)); 737 EXPECT_EQ(0, 738 audit_filter_exe(self->audit_fd, &self->audit_filter, 739 AUDIT_DEL_RULE)); 740 clear_cap(_metadata, CAP_AUDIT_CONTROL); 741 742 _exit(_metadata->exit_code); 743 return; 744 } 745 746 ASSERT_EQ(child, waitpid(child, &status, 0)); 747 if (WIFSIGNALED(status) || !WIFEXITED(status) || 748 WEXITSTATUS(status) != EXIT_SUCCESS) 749 _metadata->exit_code = KSFT_FAIL; 750 751 if (variant->restrict_flags & 752 LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF) { 753 /* 754 * No deallocation record: denials=0 never matches a real 755 * record. 756 */ 757 EXPECT_EQ(-EAGAIN, 758 matches_log_domain_deallocated(self->audit_fd, 0, 0, 759 &deallocated_dom)); 760 EXPECT_EQ(deallocated_dom, 2); 761 } else { 762 EXPECT_EQ(0, matches_log_domain_deallocated(self->audit_fd, 2, 763 *self->domain_id, 764 &deallocated_dom)); 765 EXPECT_NE(deallocated_dom, 2); 766 EXPECT_NE(deallocated_dom, 0); 767 EXPECT_EQ(deallocated_dom, *self->domain_id); 768 } 769 } 770 771 static int matches_log_fs_read_root(int audit_fd) 772 { 773 return audit_match_record( 774 audit_fd, AUDIT_LANDLOCK_ACCESS, 775 REGEX_LANDLOCK_PREFIX 776 " blockers=fs\\.read_dir path=\"/\" dev=\"[^\"]\\+\" ino=[0-9]\\+$", 777 NULL); 778 } 779 780 FIXTURE(audit_exec) 781 { 782 struct audit_filter audit_filter; 783 int audit_fd; 784 }; 785 786 FIXTURE_VARIANT(audit_exec) 787 { 788 const int restrict_flags; 789 }; 790 791 /* clang-format off */ 792 FIXTURE_VARIANT_ADD(audit_exec, default) { 793 /* clang-format on */ 794 .restrict_flags = 0, 795 }; 796 797 /* clang-format off */ 798 FIXTURE_VARIANT_ADD(audit_exec, same_exec_off) { 799 /* clang-format on */ 800 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF, 801 }; 802 803 /* clang-format off */ 804 FIXTURE_VARIANT_ADD(audit_exec, subdomains_off) { 805 /* clang-format on */ 806 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, 807 }; 808 809 /* clang-format off */ 810 FIXTURE_VARIANT_ADD(audit_exec, cross_exec_on) { 811 /* clang-format on */ 812 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON, 813 }; 814 815 /* clang-format off */ 816 FIXTURE_VARIANT_ADD(audit_exec, subdomains_off_and_cross_exec_on) { 817 /* clang-format on */ 818 .restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF | 819 LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON, 820 }; 821 822 FIXTURE_SETUP(audit_exec) 823 { 824 disable_caps(_metadata); 825 set_cap(_metadata, CAP_AUDIT_CONTROL); 826 827 self->audit_fd = audit_init(); 828 EXPECT_LE(0, self->audit_fd) 829 { 830 const char *error_msg; 831 832 /* kill "$(auditctl -s | sed -ne 's/^pid \([0-9]\+\)$/\1/p')" */ 833 if (self->audit_fd == -EEXIST) 834 error_msg = "socket already in use (e.g. auditd)"; 835 else 836 error_msg = strerror(-self->audit_fd); 837 TH_LOG("Failed to initialize audit: %s", error_msg); 838 } 839 840 /* Applies test filter for the bin_wait_pipe_sandbox program. */ 841 EXPECT_EQ(0, audit_init_filter_exe(&self->audit_filter, 842 bin_wait_pipe_sandbox)); 843 EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter, 844 AUDIT_ADD_RULE)); 845 846 clear_cap(_metadata, CAP_AUDIT_CONTROL); 847 } 848 849 FIXTURE_TEARDOWN(audit_exec) 850 { 851 set_cap(_metadata, CAP_AUDIT_CONTROL); 852 EXPECT_EQ(0, audit_filter_exe(self->audit_fd, &self->audit_filter, 853 AUDIT_DEL_RULE)); 854 clear_cap(_metadata, CAP_AUDIT_CONTROL); 855 EXPECT_EQ(0, close(self->audit_fd)); 856 } 857 858 TEST_F(audit_exec, signal_and_open) 859 { 860 struct audit_records records; 861 int pipe_child[2], pipe_parent[2]; 862 char buf_parent; 863 pid_t child; 864 int status; 865 866 ASSERT_EQ(0, pipe2(pipe_child, 0)); 867 ASSERT_EQ(0, pipe2(pipe_parent, 0)); 868 869 child = fork(); 870 ASSERT_LE(0, child); 871 if (child == 0) { 872 const struct landlock_ruleset_attr layer1 = { 873 .scoped = LANDLOCK_SCOPE_SIGNAL, 874 }; 875 char pipe_child_str[12], pipe_parent_str[12]; 876 char *const argv[] = { (char *)bin_wait_pipe_sandbox, 877 pipe_child_str, pipe_parent_str, NULL }; 878 int ruleset_fd; 879 880 /* Passes the pipe FDs to the executed binary. */ 881 EXPECT_EQ(0, close(pipe_child[0])); 882 EXPECT_EQ(0, close(pipe_parent[1])); 883 snprintf(pipe_child_str, sizeof(pipe_child_str), "%d", 884 pipe_child[1]); 885 snprintf(pipe_parent_str, sizeof(pipe_parent_str), "%d", 886 pipe_parent[0]); 887 888 ruleset_fd = 889 landlock_create_ruleset(&layer1, sizeof(layer1), 0); 890 if (ruleset_fd < 0) { 891 perror("Failed to create a ruleset"); 892 _exit(1); 893 } 894 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 895 if (landlock_restrict_self(ruleset_fd, 896 variant->restrict_flags)) { 897 perror("Failed to restrict self"); 898 _exit(1); 899 } 900 close(ruleset_fd); 901 902 ASSERT_EQ(0, execve(argv[0], argv, NULL)) 903 { 904 TH_LOG("Failed to execute \"%s\": %s", argv[0], 905 strerror(errno)); 906 }; 907 _exit(1); 908 return; 909 } 910 911 EXPECT_EQ(0, close(pipe_child[1])); 912 EXPECT_EQ(0, close(pipe_parent[0])); 913 914 /* Waits for the child. */ 915 EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 916 917 /* Tests that there was no denial until now. */ 918 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 919 EXPECT_EQ(0, records.access); 920 921 /* 922 * Wait for the child to do a first denied action by layer1 and 923 * sandbox itself with layer2. 924 */ 925 EXPECT_EQ(1, write(pipe_parent[1], ".", 1)); 926 EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 927 928 /* Tests that the audit record only matches the child. */ 929 if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) { 930 /* Matches the current domain. */ 931 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 932 getpid(), NULL)); 933 } 934 935 /* Checks that we didn't miss anything. */ 936 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 937 EXPECT_EQ(0, records.access); 938 939 /* 940 * Wait for the child to do a second denied action by layer1 and 941 * layer2, and sandbox itself with layer3. 942 */ 943 EXPECT_EQ(1, write(pipe_parent[1], ".", 1)); 944 EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 945 946 /* Tests that the audit record only matches the child. */ 947 if (variant->restrict_flags & LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON) { 948 /* Matches the current domain. */ 949 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 950 getpid(), NULL)); 951 } 952 953 if (!(variant->restrict_flags & 954 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) { 955 /* Matches the child domain. */ 956 EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd)); 957 } 958 959 /* Checks that we didn't miss anything. */ 960 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 961 EXPECT_EQ(0, records.access); 962 963 /* Waits for the child to terminate. */ 964 EXPECT_EQ(1, write(pipe_parent[1], ".", 1)); 965 ASSERT_EQ(child, waitpid(child, &status, 0)); 966 ASSERT_EQ(1, WIFEXITED(status)); 967 ASSERT_EQ(0, WEXITSTATUS(status)); 968 969 /* Tests that the audit record only matches the child. */ 970 if (!(variant->restrict_flags & 971 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF)) { 972 /* 973 * Matches the child domains, which tests that the 974 * llcred->domain_exec bitmask is correctly updated with a new 975 * domain. 976 */ 977 EXPECT_EQ(0, matches_log_fs_read_root(self->audit_fd)); 978 EXPECT_EQ(0, matches_log_signal(_metadata, self->audit_fd, 979 getpid(), NULL)); 980 } 981 982 /* Checks that we didn't miss anything. */ 983 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 984 EXPECT_EQ(0, records.access); 985 } 986 987 TEST_HARNESS_MAIN 988