1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Landlock tests - Signal Scoping 4 * 5 * Copyright © 2024 Tahera Fahimi <fahimitahera@gmail.com> 6 */ 7 8 #define _GNU_SOURCE 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <linux/landlock.h> 12 #include <pthread.h> 13 #include <signal.h> 14 #include <sys/prctl.h> 15 #include <sys/types.h> 16 #include <sys/wait.h> 17 #include <unistd.h> 18 19 #include "common.h" 20 #include "scoped_common.h" 21 22 /* This variable is used for handling several signals. */ 23 static volatile sig_atomic_t is_signaled; 24 25 /* clang-format off */ 26 FIXTURE(scoping_signals) {}; 27 /* clang-format on */ 28 29 FIXTURE_VARIANT(scoping_signals) 30 { 31 int sig; 32 }; 33 34 /* clang-format off */ 35 FIXTURE_VARIANT_ADD(scoping_signals, sigtrap) { 36 /* clang-format on */ 37 .sig = SIGTRAP, 38 }; 39 40 /* clang-format off */ 41 FIXTURE_VARIANT_ADD(scoping_signals, sigurg) { 42 /* clang-format on */ 43 .sig = SIGURG, 44 }; 45 46 /* clang-format off */ 47 FIXTURE_VARIANT_ADD(scoping_signals, sighup) { 48 /* clang-format on */ 49 .sig = SIGHUP, 50 }; 51 52 /* clang-format off */ 53 FIXTURE_VARIANT_ADD(scoping_signals, sigtstp) { 54 /* clang-format on */ 55 .sig = SIGTSTP, 56 }; 57 58 FIXTURE_SETUP(scoping_signals) 59 { 60 drop_caps(_metadata); 61 62 is_signaled = 0; 63 } 64 65 FIXTURE_TEARDOWN(scoping_signals) 66 { 67 } 68 69 static void scope_signal_handler(int sig, siginfo_t *info, void *ucontext) 70 { 71 if (sig == SIGTRAP || sig == SIGURG || sig == SIGHUP || sig == SIGTSTP) 72 is_signaled = 1; 73 } 74 75 /* 76 * In this test, a child process sends a signal to parent before and 77 * after getting scoped. 78 */ 79 TEST_F(scoping_signals, send_sig_to_parent) 80 { 81 int pipe_parent[2]; 82 int status; 83 pid_t child; 84 pid_t parent = getpid(); 85 struct sigaction action = { 86 .sa_sigaction = scope_signal_handler, 87 .sa_flags = SA_SIGINFO, 88 89 }; 90 91 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 92 ASSERT_LE(0, sigaction(variant->sig, &action, NULL)); 93 94 /* The process should not have already been signaled. */ 95 EXPECT_EQ(0, is_signaled); 96 97 child = fork(); 98 ASSERT_LE(0, child); 99 if (child == 0) { 100 char buf_child; 101 int err; 102 103 EXPECT_EQ(0, close(pipe_parent[1])); 104 105 /* 106 * The child process can send signal to parent when 107 * domain is not scoped. 108 */ 109 err = kill(parent, variant->sig); 110 ASSERT_EQ(0, err); 111 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 112 EXPECT_EQ(0, close(pipe_parent[0])); 113 114 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 115 116 /* 117 * The child process cannot send signal to the parent 118 * anymore. 119 */ 120 err = kill(parent, variant->sig); 121 ASSERT_EQ(-1, err); 122 ASSERT_EQ(EPERM, errno); 123 124 /* 125 * No matter of the domain, a process should be able to 126 * send a signal to itself. 127 */ 128 ASSERT_EQ(0, is_signaled); 129 ASSERT_EQ(0, raise(variant->sig)); 130 ASSERT_EQ(1, is_signaled); 131 132 _exit(_metadata->exit_code); 133 return; 134 } 135 EXPECT_EQ(0, close(pipe_parent[0])); 136 137 /* Waits for a first signal to be received, without race condition. */ 138 while (!is_signaled && !usleep(1)) 139 ; 140 ASSERT_EQ(1, is_signaled); 141 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 142 EXPECT_EQ(0, close(pipe_parent[1])); 143 is_signaled = 0; 144 145 ASSERT_EQ(child, waitpid(child, &status, 0)); 146 if (WIFSIGNALED(status) || !WIFEXITED(status) || 147 WEXITSTATUS(status) != EXIT_SUCCESS) 148 _metadata->exit_code = KSFT_FAIL; 149 150 EXPECT_EQ(0, is_signaled); 151 } 152 153 /* clang-format off */ 154 FIXTURE(scoped_domains) {}; 155 /* clang-format on */ 156 157 #include "scoped_base_variants.h" 158 159 FIXTURE_SETUP(scoped_domains) 160 { 161 drop_caps(_metadata); 162 } 163 164 FIXTURE_TEARDOWN(scoped_domains) 165 { 166 } 167 168 /* 169 * This test ensures that a scoped process cannot send signal out of 170 * scoped domain. 171 */ 172 TEST_F(scoped_domains, check_access_signal) 173 { 174 pid_t child; 175 pid_t parent = getpid(); 176 int status; 177 bool can_signal_child, can_signal_parent; 178 int pipe_parent[2], pipe_child[2]; 179 char buf_parent; 180 int err; 181 182 can_signal_parent = !variant->domain_child; 183 can_signal_child = !variant->domain_parent; 184 185 if (variant->domain_both) 186 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 187 188 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 189 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 190 191 child = fork(); 192 ASSERT_LE(0, child); 193 if (child == 0) { 194 char buf_child; 195 196 EXPECT_EQ(0, close(pipe_child[0])); 197 EXPECT_EQ(0, close(pipe_parent[1])); 198 199 if (variant->domain_child) 200 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 201 202 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 203 EXPECT_EQ(0, close(pipe_child[1])); 204 205 /* Waits for the parent to send signals. */ 206 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 207 EXPECT_EQ(0, close(pipe_parent[0])); 208 209 err = kill(parent, 0); 210 if (can_signal_parent) { 211 ASSERT_EQ(0, err); 212 } else { 213 ASSERT_EQ(-1, err); 214 ASSERT_EQ(EPERM, errno); 215 } 216 /* 217 * No matter of the domain, a process should be able to 218 * send a signal to itself. 219 */ 220 ASSERT_EQ(0, raise(0)); 221 222 _exit(_metadata->exit_code); 223 return; 224 } 225 EXPECT_EQ(0, close(pipe_parent[0])); 226 EXPECT_EQ(0, close(pipe_child[1])); 227 228 if (variant->domain_parent) 229 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 230 231 ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 232 EXPECT_EQ(0, close(pipe_child[0])); 233 234 err = kill(child, 0); 235 if (can_signal_child) { 236 ASSERT_EQ(0, err); 237 } else { 238 ASSERT_EQ(-1, err); 239 ASSERT_EQ(EPERM, errno); 240 } 241 ASSERT_EQ(0, raise(0)); 242 243 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 244 EXPECT_EQ(0, close(pipe_parent[1])); 245 ASSERT_EQ(child, waitpid(child, &status, 0)); 246 247 if (WIFSIGNALED(status) || !WIFEXITED(status) || 248 WEXITSTATUS(status) != EXIT_SUCCESS) 249 _metadata->exit_code = KSFT_FAIL; 250 } 251 252 enum thread_return { 253 THREAD_INVALID = 0, 254 THREAD_SUCCESS = 1, 255 THREAD_ERROR = 2, 256 THREAD_TEST_FAILED = 3, 257 }; 258 259 static void *thread_sync(void *arg) 260 { 261 const int pipe_read = *(int *)arg; 262 char buf; 263 264 if (read(pipe_read, &buf, 1) != 1) 265 return (void *)THREAD_ERROR; 266 267 return (void *)THREAD_SUCCESS; 268 } 269 270 TEST(signal_scoping_thread_before) 271 { 272 pthread_t no_sandbox_thread; 273 enum thread_return ret = THREAD_INVALID; 274 int thread_pipe[2]; 275 276 drop_caps(_metadata); 277 ASSERT_EQ(0, pipe2(thread_pipe, O_CLOEXEC)); 278 279 ASSERT_EQ(0, pthread_create(&no_sandbox_thread, NULL, thread_sync, 280 &thread_pipe[0])); 281 282 /* Enforces restriction after creating the thread. */ 283 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 284 285 EXPECT_EQ(0, pthread_kill(no_sandbox_thread, 0)); 286 EXPECT_EQ(1, write(thread_pipe[1], ".", 1)); 287 288 EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret)); 289 EXPECT_EQ(THREAD_SUCCESS, ret); 290 291 EXPECT_EQ(0, close(thread_pipe[0])); 292 EXPECT_EQ(0, close(thread_pipe[1])); 293 } 294 295 TEST(signal_scoping_thread_after) 296 { 297 pthread_t scoped_thread; 298 enum thread_return ret = THREAD_INVALID; 299 int thread_pipe[2]; 300 301 drop_caps(_metadata); 302 ASSERT_EQ(0, pipe2(thread_pipe, O_CLOEXEC)); 303 304 /* Enforces restriction before creating the thread. */ 305 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 306 307 ASSERT_EQ(0, pthread_create(&scoped_thread, NULL, thread_sync, 308 &thread_pipe[0])); 309 310 EXPECT_EQ(0, pthread_kill(scoped_thread, 0)); 311 EXPECT_EQ(1, write(thread_pipe[1], ".", 1)); 312 313 EXPECT_EQ(0, pthread_join(scoped_thread, (void **)&ret)); 314 EXPECT_EQ(THREAD_SUCCESS, ret); 315 316 EXPECT_EQ(0, close(thread_pipe[0])); 317 EXPECT_EQ(0, close(thread_pipe[1])); 318 } 319 320 struct thread_setuid_args { 321 int pipe_read, new_uid; 322 }; 323 324 void *thread_setuid(void *ptr) 325 { 326 const struct thread_setuid_args *arg = ptr; 327 char buf; 328 329 if (read(arg->pipe_read, &buf, 1) != 1) 330 return (void *)THREAD_ERROR; 331 332 /* libc's setuid() should update all thread's credentials. */ 333 if (getuid() != arg->new_uid) 334 return (void *)THREAD_TEST_FAILED; 335 336 return (void *)THREAD_SUCCESS; 337 } 338 339 TEST(signal_scoping_thread_setuid) 340 { 341 struct thread_setuid_args arg; 342 pthread_t no_sandbox_thread; 343 enum thread_return ret = THREAD_INVALID; 344 int pipe_parent[2]; 345 int prev_uid; 346 347 disable_caps(_metadata); 348 349 /* This test does not need to be run as root. */ 350 prev_uid = getuid(); 351 arg.new_uid = prev_uid + 1; 352 EXPECT_LT(0, arg.new_uid); 353 354 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 355 arg.pipe_read = pipe_parent[0]; 356 357 /* Capabilities must be set before creating a new thread. */ 358 set_cap(_metadata, CAP_SETUID); 359 ASSERT_EQ(0, pthread_create(&no_sandbox_thread, NULL, thread_setuid, 360 &arg)); 361 362 /* Enforces restriction after creating the thread. */ 363 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 364 365 EXPECT_NE(arg.new_uid, getuid()); 366 EXPECT_EQ(0, setuid(arg.new_uid)); 367 EXPECT_EQ(arg.new_uid, getuid()); 368 EXPECT_EQ(1, write(pipe_parent[1], ".", 1)); 369 370 EXPECT_EQ(0, pthread_join(no_sandbox_thread, (void **)&ret)); 371 EXPECT_EQ(THREAD_SUCCESS, ret); 372 373 clear_cap(_metadata, CAP_SETUID); 374 EXPECT_EQ(0, close(pipe_parent[0])); 375 EXPECT_EQ(0, close(pipe_parent[1])); 376 } 377 378 const short backlog = 10; 379 380 static volatile sig_atomic_t signal_received; 381 382 static void handle_sigurg(int sig) 383 { 384 if (sig == SIGURG) 385 signal_received = 1; 386 else 387 signal_received = -1; 388 } 389 390 static int setup_signal_handler(int signal) 391 { 392 struct sigaction sa = { 393 .sa_handler = handle_sigurg, 394 }; 395 396 if (sigemptyset(&sa.sa_mask)) 397 return -1; 398 399 sa.sa_flags = SA_SIGINFO | SA_RESTART; 400 return sigaction(SIGURG, &sa, NULL); 401 } 402 403 /* clang-format off */ 404 FIXTURE(fown) {}; 405 /* clang-format on */ 406 407 enum fown_sandbox { 408 SANDBOX_NONE, 409 SANDBOX_BEFORE_FORK, 410 SANDBOX_BEFORE_SETOWN, 411 SANDBOX_AFTER_SETOWN, 412 }; 413 414 FIXTURE_VARIANT(fown) 415 { 416 const enum fown_sandbox sandbox_setown; 417 }; 418 419 /* clang-format off */ 420 FIXTURE_VARIANT_ADD(fown, no_sandbox) { 421 /* clang-format on */ 422 .sandbox_setown = SANDBOX_NONE, 423 }; 424 425 /* clang-format off */ 426 FIXTURE_VARIANT_ADD(fown, sandbox_before_fork) { 427 /* clang-format on */ 428 .sandbox_setown = SANDBOX_BEFORE_FORK, 429 }; 430 431 /* clang-format off */ 432 FIXTURE_VARIANT_ADD(fown, sandbox_before_setown) { 433 /* clang-format on */ 434 .sandbox_setown = SANDBOX_BEFORE_SETOWN, 435 }; 436 437 /* clang-format off */ 438 FIXTURE_VARIANT_ADD(fown, sandbox_after_setown) { 439 /* clang-format on */ 440 .sandbox_setown = SANDBOX_AFTER_SETOWN, 441 }; 442 443 FIXTURE_SETUP(fown) 444 { 445 drop_caps(_metadata); 446 } 447 448 FIXTURE_TEARDOWN(fown) 449 { 450 } 451 452 /* 453 * Sending an out of bound message will trigger the SIGURG signal 454 * through file_send_sigiotask. 455 */ 456 TEST_F(fown, sigurg_socket) 457 { 458 int server_socket, recv_socket; 459 struct service_fixture server_address; 460 char buffer_parent; 461 int status; 462 int pipe_parent[2], pipe_child[2]; 463 pid_t child; 464 465 memset(&server_address, 0, sizeof(server_address)); 466 set_unix_address(&server_address, 0); 467 468 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 469 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 470 471 if (variant->sandbox_setown == SANDBOX_BEFORE_FORK) 472 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 473 474 child = fork(); 475 ASSERT_LE(0, child); 476 if (child == 0) { 477 int client_socket; 478 char buffer_child; 479 480 EXPECT_EQ(0, close(pipe_parent[1])); 481 EXPECT_EQ(0, close(pipe_child[0])); 482 483 ASSERT_EQ(0, setup_signal_handler(SIGURG)); 484 client_socket = socket(AF_UNIX, SOCK_STREAM, 0); 485 ASSERT_LE(0, client_socket); 486 487 /* Waits for the parent to listen. */ 488 ASSERT_EQ(1, read(pipe_parent[0], &buffer_child, 1)); 489 ASSERT_EQ(0, connect(client_socket, &server_address.unix_addr, 490 server_address.unix_addr_len)); 491 492 /* 493 * Waits for the parent to accept the connection, sandbox 494 * itself, and call fcntl(2). 495 */ 496 ASSERT_EQ(1, read(pipe_parent[0], &buffer_child, 1)); 497 /* May signal itself. */ 498 ASSERT_EQ(1, send(client_socket, ".", 1, MSG_OOB)); 499 EXPECT_EQ(0, close(client_socket)); 500 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 501 EXPECT_EQ(0, close(pipe_child[1])); 502 503 /* Waits for the message to be received. */ 504 ASSERT_EQ(1, read(pipe_parent[0], &buffer_child, 1)); 505 EXPECT_EQ(0, close(pipe_parent[0])); 506 507 if (variant->sandbox_setown == SANDBOX_BEFORE_SETOWN) { 508 ASSERT_EQ(0, signal_received); 509 } else { 510 /* 511 * A signal is only received if fcntl(F_SETOWN) was 512 * called before any sandboxing or if the signal 513 * receiver is in the same domain. 514 */ 515 ASSERT_EQ(1, signal_received); 516 } 517 _exit(_metadata->exit_code); 518 return; 519 } 520 EXPECT_EQ(0, close(pipe_parent[0])); 521 EXPECT_EQ(0, close(pipe_child[1])); 522 523 server_socket = socket(AF_UNIX, SOCK_STREAM, 0); 524 ASSERT_LE(0, server_socket); 525 ASSERT_EQ(0, bind(server_socket, &server_address.unix_addr, 526 server_address.unix_addr_len)); 527 ASSERT_EQ(0, listen(server_socket, backlog)); 528 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 529 530 recv_socket = accept(server_socket, NULL, NULL); 531 ASSERT_LE(0, recv_socket); 532 533 if (variant->sandbox_setown == SANDBOX_BEFORE_SETOWN) 534 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 535 536 /* 537 * Sets the child to receive SIGURG for MSG_OOB. This uncommon use is 538 * a valid attack scenario which also simplifies this test. 539 */ 540 ASSERT_EQ(0, fcntl(recv_socket, F_SETOWN, child)); 541 542 if (variant->sandbox_setown == SANDBOX_AFTER_SETOWN) 543 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 544 545 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 546 547 /* Waits for the child to send MSG_OOB. */ 548 ASSERT_EQ(1, read(pipe_child[0], &buffer_parent, 1)); 549 EXPECT_EQ(0, close(pipe_child[0])); 550 ASSERT_EQ(1, recv(recv_socket, &buffer_parent, 1, MSG_OOB)); 551 EXPECT_EQ(0, close(recv_socket)); 552 EXPECT_EQ(0, close(server_socket)); 553 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 554 EXPECT_EQ(0, close(pipe_parent[1])); 555 556 ASSERT_EQ(child, waitpid(child, &status, 0)); 557 if (WIFSIGNALED(status) || !WIFEXITED(status) || 558 WEXITSTATUS(status) != EXIT_SUCCESS) 559 _metadata->exit_code = KSFT_FAIL; 560 } 561 562 /* 563 * Checks that LANDLOCK_SCOPE_SIGNAL is enforced on the asynchronous SIGIO 564 * delivery path (fcntl(F_SETOWN)) when the file owner is a process group. 565 * 566 * A sandboxed process sitting at the head of its process group's PID hlist (the 567 * default position right after fork()) used to escape the fcntl(F_SETOWN, 568 * -pgrp) domain recording: pid_task(pgrp, PIDTYPE_PGID) resolved to the process 569 * itself, so the same-thread-group exemption skipped recording its Landlock 570 * domain. At SIGIO time that domain was then unset and the signal fanned out 571 * to every group member, including non-sandboxed processes outside the domain. 572 */ 573 TEST(sigio_to_pgid_members) 574 { 575 int trigger[2], sync_child[2]; 576 char buf; 577 pid_t child; 578 int status, i; 579 580 drop_caps(_metadata); 581 582 /* 583 * Isolates the test in its own process group so the SIGIO fan-out stays 584 * bounded to this parent and the child forked below. 585 */ 586 ASSERT_EQ(0, setpgid(0, 0)); 587 588 /* The non-sandboxed parent is the protected (out-of-domain) target. */ 589 ASSERT_EQ(0, setup_signal_handler(SIGURG)); 590 signal_received = 0; 591 592 ASSERT_EQ(0, pipe2(trigger, O_CLOEXEC)); 593 ASSERT_EQ(0, pipe2(sync_child, O_CLOEXEC)); 594 595 child = fork(); 596 ASSERT_LE(0, child); 597 if (child == 0) { 598 /* 599 * The child inherits the parent's new process group and, just 600 * attached with hlist_add_head_rcu(), is now the head of the 601 * pgid hlist: this is the case that used to skip the recording. 602 */ 603 EXPECT_EQ(0, close(sync_child[0])); 604 605 /* In-domain positive control: the child must be signaled. */ 606 ASSERT_EQ(0, setup_signal_handler(SIGURG)); 607 signal_received = 0; 608 609 create_scoped_domain(_metadata, LANDLOCK_SCOPE_SIGNAL); 610 611 /* Owns the SIGIO source for the whole process group. */ 612 ASSERT_EQ(0, fcntl(trigger[0], F_SETSIG, SIGURG)); 613 ASSERT_EQ(0, fcntl(trigger[0], F_SETOWN, -getpgrp())); 614 ASSERT_EQ(0, fcntl(trigger[0], F_SETFL, O_ASYNC)); 615 616 /* Fans SIGURG out to every member of the process group. */ 617 ASSERT_EQ(1, write(trigger[1], ".", 1)); 618 619 /* 620 * The sandboxed child is in its own domain and must always be 621 * signaled: this proves the SIGIO actually fired. 622 */ 623 for (i = 0; i < 1000 && !signal_received; i++) 624 usleep(1000); 625 EXPECT_EQ(1, signal_received); 626 627 ASSERT_EQ(1, write(sync_child[1], ".", 1)); 628 EXPECT_EQ(0, close(sync_child[1])); 629 630 _exit(_metadata->exit_code); 631 return; 632 } 633 EXPECT_EQ(0, close(sync_child[1])); 634 EXPECT_EQ(0, close(trigger[0])); 635 EXPECT_EQ(0, close(trigger[1])); 636 637 /* Waits for the child to generate the SIGIO. */ 638 ASSERT_EQ(1, read(sync_child[0], &buf, 1)); 639 EXPECT_EQ(0, close(sync_child[0])); 640 641 /* Lets a delivered-but-pending signal run our handler, if any. */ 642 for (i = 0; i < 100 && !signal_received; i++) 643 usleep(1000); 644 645 /* 646 * SCOPE_SIGNAL must block the fan-out to this non-sandboxed parent, 647 * which is outside the child's Landlock domain. Before the fix the 648 * parent was signaled here. 649 */ 650 EXPECT_EQ(0, signal_received); 651 652 ASSERT_EQ(child, waitpid(child, &status, 0)); 653 if (WIFSIGNALED(status) || !WIFEXITED(status) || 654 WEXITSTATUS(status) != EXIT_SUCCESS) 655 _metadata->exit_code = KSFT_FAIL; 656 } 657 658 static void *thread_setown_scoped(void *arg) 659 { 660 const int fd = *(int *)arg; 661 int ruleset_fd; 662 const struct landlock_ruleset_attr ruleset_attr = { 663 .scoped = LANDLOCK_SCOPE_SIGNAL, 664 }; 665 666 /* Sandboxes only this non-leader thread (no thread syncing). */ 667 ruleset_fd = 668 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 669 if (ruleset_fd < 0) 670 return (void *)THREAD_ERROR; 671 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || 672 landlock_restrict_self(ruleset_fd, 0)) { 673 close(ruleset_fd); 674 return (void *)THREAD_ERROR; 675 } 676 close(ruleset_fd); 677 678 /* Makes this process group own the SIGIO source. */ 679 if (fcntl(fd, F_SETSIG, SIGURG) || fcntl(fd, F_SETOWN, -getpgrp()) || 680 fcntl(fd, F_SETFL, O_ASYNC)) 681 return (void *)THREAD_ERROR; 682 683 return (void *)THREAD_SUCCESS; 684 } 685 686 /* 687 * Checks that the SIGIO fan-out is still delivered to the file owner's own 688 * process when fcntl(F_SETOWN, -pgrp) was issued from a sandboxed non-leader 689 * thread. 690 * 691 * The Landlock domain is recorded for a process-group owner (so out-of-domain 692 * members stay blocked, see sigio_to_pgid_members), but the kernel signals a 693 * process group through its members' thread-group leaders. Here the leader is 694 * not sandboxed and thus has a different domain than the registering thread, so 695 * the registration-time check cannot tell that it belongs to the owner's own 696 * process. hook_file_send_sigiotask() must recognize it through the recorded 697 * thread group and allow the delivery, matching the same-process guarantee of 698 * commit 18eb75f3af40. Without that exemption the leader is wrongly denied and 699 * never signaled. 700 */ 701 TEST(sigio_to_pgid_self) 702 { 703 int trigger[2]; 704 pthread_t thread; 705 enum thread_return ret = THREAD_INVALID; 706 int i; 707 708 drop_caps(_metadata); 709 710 /* Bounds the SIGIO fan-out to this process. */ 711 ASSERT_EQ(0, setpgid(0, 0)); 712 713 /* The non-sandboxed thread-group leader is the SIGIO target. */ 714 ASSERT_EQ(0, setup_signal_handler(SIGURG)); 715 signal_received = 0; 716 717 ASSERT_EQ(0, pipe2(trigger, O_CLOEXEC)); 718 719 /* 720 * Registers the process-group fowner from a sibling thread that 721 * sandboxes only itself, so its domain differs from the leader's. 722 */ 723 ASSERT_EQ(0, pthread_create(&thread, NULL, thread_setown_scoped, 724 &trigger[0])); 725 ASSERT_EQ(0, pthread_join(thread, (void **)&ret)); 726 ASSERT_EQ(THREAD_SUCCESS, ret); 727 728 /* Fans SIGURG out to the process group. */ 729 ASSERT_EQ(1, write(trigger[1], ".", 1)); 730 731 for (i = 0; i < 1000 && !signal_received; i++) 732 usleep(1000); 733 734 /* 735 * Same-process delivery must always be allowed, even though the owner 736 * was registered from a sandboxed sibling thread. 737 */ 738 EXPECT_EQ(1, signal_received); 739 740 EXPECT_EQ(0, close(trigger[0])); 741 EXPECT_EQ(0, close(trigger[1])); 742 } 743 744 TEST_HARNESS_MAIN 745