1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Landlock tests - Abstract UNIX socket 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 <sched.h> 13 #include <signal.h> 14 #include <stddef.h> 15 #include <sys/mount.h> 16 #include <sys/prctl.h> 17 #include <sys/socket.h> 18 #include <sys/stat.h> 19 #include <sys/types.h> 20 #include <sys/un.h> 21 #include <sys/wait.h> 22 #include <unistd.h> 23 24 #include "audit.h" 25 #include "common.h" 26 #include "scoped_common.h" 27 #include "trace.h" 28 29 #define TRACE_TASK "scoped_abstract" 30 31 /* Number of pending connections queue to be hold. */ 32 const short backlog = 10; 33 34 static void create_fs_domain(struct __test_metadata *const _metadata) 35 { 36 int ruleset_fd; 37 struct landlock_ruleset_attr ruleset_attr = { 38 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR, 39 }; 40 41 ruleset_fd = 42 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 43 EXPECT_LE(0, ruleset_fd) 44 { 45 TH_LOG("Failed to create a ruleset: %s", strerror(errno)); 46 } 47 EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); 48 EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0)); 49 EXPECT_EQ(0, close(ruleset_fd)); 50 } 51 52 FIXTURE(scoped_domains) 53 { 54 struct service_fixture stream_address, dgram_address; 55 }; 56 57 #include "scoped_base_variants.h" 58 59 FIXTURE_SETUP(scoped_domains) 60 { 61 drop_caps(_metadata); 62 63 memset(&self->stream_address, 0, sizeof(self->stream_address)); 64 memset(&self->dgram_address, 0, sizeof(self->dgram_address)); 65 set_unix_address(&self->stream_address, 0); 66 set_unix_address(&self->dgram_address, 1); 67 } 68 69 FIXTURE_TEARDOWN(scoped_domains) 70 { 71 } 72 73 /* 74 * Test unix_stream_connect() and unix_may_send() for a child connecting to its 75 * parent, when they have scoped domain or no domain. 76 */ 77 TEST_F(scoped_domains, connect_to_parent) 78 { 79 pid_t child; 80 bool can_connect_to_parent; 81 int status; 82 int pipe_parent[2]; 83 int stream_server, dgram_server; 84 85 /* 86 * can_connect_to_parent is true if a child process can connect to its 87 * parent process. This depends on the child process not being isolated 88 * from the parent with a dedicated Landlock domain. 89 */ 90 can_connect_to_parent = !variant->domain_child; 91 92 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 93 if (variant->domain_both) { 94 create_scoped_domain(_metadata, 95 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 96 if (!__test_passed(_metadata)) 97 return; 98 } 99 100 child = fork(); 101 ASSERT_LE(0, child); 102 if (child == 0) { 103 int err; 104 int stream_client, dgram_client; 105 char buf_child; 106 107 EXPECT_EQ(0, close(pipe_parent[1])); 108 if (variant->domain_child) 109 create_scoped_domain( 110 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 111 112 stream_client = socket(AF_UNIX, SOCK_STREAM, 0); 113 ASSERT_LE(0, stream_client); 114 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0); 115 ASSERT_LE(0, dgram_client); 116 117 /* Waits for the server. */ 118 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 119 120 err = connect(stream_client, &self->stream_address.unix_addr, 121 self->stream_address.unix_addr_len); 122 if (can_connect_to_parent) { 123 EXPECT_EQ(0, err); 124 } else { 125 EXPECT_EQ(-1, err); 126 EXPECT_EQ(EPERM, errno); 127 } 128 EXPECT_EQ(0, close(stream_client)); 129 130 err = connect(dgram_client, &self->dgram_address.unix_addr, 131 self->dgram_address.unix_addr_len); 132 if (can_connect_to_parent) { 133 EXPECT_EQ(0, err); 134 } else { 135 EXPECT_EQ(-1, err); 136 EXPECT_EQ(EPERM, errno); 137 } 138 EXPECT_EQ(0, close(dgram_client)); 139 _exit(_metadata->exit_code); 140 return; 141 } 142 EXPECT_EQ(0, close(pipe_parent[0])); 143 if (variant->domain_parent) 144 create_scoped_domain(_metadata, 145 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 146 147 stream_server = socket(AF_UNIX, SOCK_STREAM, 0); 148 ASSERT_LE(0, stream_server); 149 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0); 150 ASSERT_LE(0, dgram_server); 151 ASSERT_EQ(0, bind(stream_server, &self->stream_address.unix_addr, 152 self->stream_address.unix_addr_len)); 153 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr, 154 self->dgram_address.unix_addr_len)); 155 ASSERT_EQ(0, listen(stream_server, backlog)); 156 157 /* Signals to child that the parent is listening. */ 158 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 159 160 ASSERT_EQ(child, waitpid(child, &status, 0)); 161 EXPECT_EQ(0, close(stream_server)); 162 EXPECT_EQ(0, close(dgram_server)); 163 164 if (WIFSIGNALED(status) || !WIFEXITED(status) || 165 WEXITSTATUS(status) != EXIT_SUCCESS) 166 _metadata->exit_code = KSFT_FAIL; 167 } 168 169 /* 170 * Test unix_stream_connect() and unix_may_send() for a parent connecting to 171 * its child, when they have scoped domain or no domain. 172 */ 173 TEST_F(scoped_domains, connect_to_child) 174 { 175 pid_t child; 176 bool can_connect_to_child; 177 int err_stream, err_dgram, errno_stream, errno_dgram, status; 178 int pipe_child[2], pipe_parent[2]; 179 char buf; 180 int stream_client, dgram_client; 181 182 /* 183 * can_connect_to_child is true if a parent process can connect to its 184 * child process. The parent process is not isolated from the child 185 * with a dedicated Landlock domain. 186 */ 187 can_connect_to_child = !variant->domain_parent; 188 189 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 190 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 191 if (variant->domain_both) { 192 create_scoped_domain(_metadata, 193 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 194 if (!__test_passed(_metadata)) 195 return; 196 } 197 198 child = fork(); 199 ASSERT_LE(0, child); 200 if (child == 0) { 201 int stream_server, dgram_server; 202 203 EXPECT_EQ(0, close(pipe_parent[1])); 204 EXPECT_EQ(0, close(pipe_child[0])); 205 if (variant->domain_child) 206 create_scoped_domain( 207 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 208 209 /* Waits for the parent to be in a domain, if any. */ 210 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 211 212 stream_server = socket(AF_UNIX, SOCK_STREAM, 0); 213 ASSERT_LE(0, stream_server); 214 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0); 215 ASSERT_LE(0, dgram_server); 216 ASSERT_EQ(0, 217 bind(stream_server, &self->stream_address.unix_addr, 218 self->stream_address.unix_addr_len)); 219 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr, 220 self->dgram_address.unix_addr_len)); 221 ASSERT_EQ(0, listen(stream_server, backlog)); 222 223 /* Signals to the parent that child is listening. */ 224 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 225 226 /* Waits to connect. */ 227 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 228 EXPECT_EQ(0, close(stream_server)); 229 EXPECT_EQ(0, close(dgram_server)); 230 _exit(_metadata->exit_code); 231 return; 232 } 233 EXPECT_EQ(0, close(pipe_child[1])); 234 EXPECT_EQ(0, close(pipe_parent[0])); 235 236 if (variant->domain_parent) 237 create_scoped_domain(_metadata, 238 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 239 240 /* Signals that the parent is in a domain, if any. */ 241 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 242 243 stream_client = socket(AF_UNIX, SOCK_STREAM, 0); 244 ASSERT_LE(0, stream_client); 245 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0); 246 ASSERT_LE(0, dgram_client); 247 248 /* Waits for the child to listen */ 249 ASSERT_EQ(1, read(pipe_child[0], &buf, 1)); 250 err_stream = connect(stream_client, &self->stream_address.unix_addr, 251 self->stream_address.unix_addr_len); 252 errno_stream = errno; 253 err_dgram = connect(dgram_client, &self->dgram_address.unix_addr, 254 self->dgram_address.unix_addr_len); 255 errno_dgram = errno; 256 if (can_connect_to_child) { 257 EXPECT_EQ(0, err_stream); 258 EXPECT_EQ(0, err_dgram); 259 } else { 260 EXPECT_EQ(-1, err_stream); 261 EXPECT_EQ(-1, err_dgram); 262 EXPECT_EQ(EPERM, errno_stream); 263 EXPECT_EQ(EPERM, errno_dgram); 264 } 265 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 266 EXPECT_EQ(0, close(stream_client)); 267 EXPECT_EQ(0, close(dgram_client)); 268 269 ASSERT_EQ(child, waitpid(child, &status, 0)); 270 if (WIFSIGNALED(status) || !WIFEXITED(status) || 271 WEXITSTATUS(status) != EXIT_SUCCESS) 272 _metadata->exit_code = KSFT_FAIL; 273 } 274 275 FIXTURE(scoped_audit) 276 { 277 struct service_fixture dgram_address; 278 struct audit_filter audit_filter; 279 int audit_fd; 280 }; 281 282 FIXTURE_SETUP(scoped_audit) 283 { 284 disable_caps(_metadata); 285 286 memset(&self->dgram_address, 0, sizeof(self->dgram_address)); 287 set_unix_address(&self->dgram_address, 1); 288 289 set_cap(_metadata, CAP_AUDIT_CONTROL); 290 self->audit_fd = audit_init_with_exe_filter(&self->audit_filter); 291 EXPECT_LE(0, self->audit_fd); 292 drop_caps(_metadata); 293 } 294 295 FIXTURE_TEARDOWN_PARENT(scoped_audit) 296 { 297 EXPECT_EQ(0, audit_cleanup(-1, NULL)); 298 } 299 300 FIXTURE_VARIANT(scoped_audit) 301 { 302 const __u64 scoped; 303 const __u64 quiet_scoped; 304 }; 305 306 /* clang-format off */ 307 FIXTURE_VARIANT_ADD(scoped_audit, no_quiet) 308 { 309 /* clang-format on */ 310 .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, 311 .quiet_scoped = 0, 312 }; 313 314 /* clang-format off */ 315 FIXTURE_VARIANT_ADD(scoped_audit, quiet_abstract_socket) 316 { 317 /* clang-format on */ 318 .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, 319 .quiet_scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, 320 }; 321 322 /* clang-format off */ 323 FIXTURE_VARIANT_ADD(scoped_audit, quiet_abstract_socket_2) 324 { 325 /* clang-format on */ 326 .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | LANDLOCK_SCOPE_SIGNAL, 327 .quiet_scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | 328 LANDLOCK_SCOPE_SIGNAL, 329 }; 330 331 /* clang-format off */ 332 FIXTURE_VARIANT_ADD(scoped_audit, quiet_unrelated) 333 { 334 /* clang-format on */ 335 .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | LANDLOCK_SCOPE_SIGNAL, 336 .quiet_scoped = LANDLOCK_SCOPE_SIGNAL, 337 }; 338 339 /* python -c 'print(b"\0selftests-landlock-abstract-unix-".hex().upper())' */ 340 #define ABSTRACT_SOCKET_PATH_PREFIX \ 341 "0073656C6674657374732D6C616E646C6F636B2D61627374726163742D756E69782D" 342 343 /* 344 * Simpler version of scoped_domains.connect_to_child, but with audit tests. 345 */ 346 TEST_F(scoped_audit, connect_to_child) 347 { 348 pid_t child; 349 int err_dgram, status; 350 int pipe_child[2], pipe_parent[2]; 351 char buf; 352 int dgram_client; 353 struct audit_records records; 354 int ruleset_fd; 355 const struct landlock_ruleset_attr ruleset_attr = { 356 .scoped = variant->scoped, 357 .quiet_scoped = variant->quiet_scoped, 358 }; 359 bool should_audit = 360 !(variant->quiet_scoped & LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 361 362 /* Makes sure there is no superfluous logged records. */ 363 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 364 EXPECT_EQ(0, records.access); 365 EXPECT_EQ(0, records.domain); 366 367 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 368 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 369 370 child = fork(); 371 ASSERT_LE(0, child); 372 if (child == 0) { 373 int dgram_server; 374 375 EXPECT_EQ(0, close(pipe_parent[1])); 376 EXPECT_EQ(0, close(pipe_child[0])); 377 378 /* Waits for the parent to be in a domain. */ 379 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 380 381 dgram_server = socket(AF_UNIX, SOCK_DGRAM, 0); 382 ASSERT_LE(0, dgram_server); 383 ASSERT_EQ(0, bind(dgram_server, &self->dgram_address.unix_addr, 384 self->dgram_address.unix_addr_len)); 385 386 /* Signals to the parent that child is listening. */ 387 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 388 389 /* Waits to connect. */ 390 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 391 EXPECT_EQ(0, close(dgram_server)); 392 _exit(_metadata->exit_code); 393 return; 394 } 395 EXPECT_EQ(0, close(pipe_child[1])); 396 EXPECT_EQ(0, close(pipe_parent[0])); 397 398 ruleset_fd = 399 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 400 ASSERT_LE(0, ruleset_fd) 401 { 402 TH_LOG("Failed to create a ruleset: %s", strerror(errno)); 403 } 404 enforce_ruleset(_metadata, ruleset_fd); 405 EXPECT_EQ(0, close(ruleset_fd)); 406 407 /* Signals that the parent is in a domain, if any. */ 408 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 409 410 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0); 411 ASSERT_LE(0, dgram_client); 412 413 /* Waits for the child to listen */ 414 ASSERT_EQ(1, read(pipe_child[0], &buf, 1)); 415 err_dgram = connect(dgram_client, &self->dgram_address.unix_addr, 416 self->dgram_address.unix_addr_len); 417 EXPECT_EQ(-1, err_dgram); 418 EXPECT_EQ(EPERM, errno); 419 420 if (should_audit) { 421 EXPECT_EQ( 422 0, 423 audit_match_record( 424 self->audit_fd, AUDIT_LANDLOCK_ACCESS, 425 REGEX_LANDLOCK_PREFIX 426 " blockers=scope\\.abstract_unix_socket path=" ABSTRACT_SOCKET_PATH_PREFIX 427 "[0-9A-F]\\+$", 428 NULL)); 429 } 430 431 /* No other logs */ 432 EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 433 EXPECT_EQ(0, records.access); 434 435 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 436 EXPECT_EQ(0, close(dgram_client)); 437 438 ASSERT_EQ(child, waitpid(child, &status, 0)); 439 if (WIFSIGNALED(status) || !WIFEXITED(status) || 440 WEXITSTATUS(status) != EXIT_SUCCESS) 441 _metadata->exit_code = KSFT_FAIL; 442 } 443 444 FIXTURE(scoped_vs_unscoped) 445 { 446 struct service_fixture parent_stream_address, parent_dgram_address, 447 child_stream_address, child_dgram_address; 448 }; 449 450 #include "scoped_multiple_domain_variants.h" 451 452 FIXTURE_SETUP(scoped_vs_unscoped) 453 { 454 drop_caps(_metadata); 455 456 memset(&self->parent_stream_address, 0, 457 sizeof(self->parent_stream_address)); 458 set_unix_address(&self->parent_stream_address, 0); 459 memset(&self->parent_dgram_address, 0, 460 sizeof(self->parent_dgram_address)); 461 set_unix_address(&self->parent_dgram_address, 1); 462 memset(&self->child_stream_address, 0, 463 sizeof(self->child_stream_address)); 464 set_unix_address(&self->child_stream_address, 2); 465 memset(&self->child_dgram_address, 0, 466 sizeof(self->child_dgram_address)); 467 set_unix_address(&self->child_dgram_address, 3); 468 } 469 470 FIXTURE_TEARDOWN(scoped_vs_unscoped) 471 { 472 } 473 474 /* 475 * Test unix_stream_connect and unix_may_send for parent, child and 476 * grand child processes when they can have scoped or non-scoped domains. 477 */ 478 TEST_F(scoped_vs_unscoped, unix_scoping) 479 { 480 pid_t child; 481 int status; 482 bool can_connect_to_parent, can_connect_to_child; 483 int pipe_parent[2]; 484 int stream_server_parent, dgram_server_parent; 485 486 can_connect_to_child = (variant->domain_grand_child != SCOPE_SANDBOX); 487 can_connect_to_parent = (can_connect_to_child && 488 (variant->domain_children != SCOPE_SANDBOX)); 489 490 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 491 492 if (variant->domain_all == OTHER_SANDBOX) 493 create_fs_domain(_metadata); 494 else if (variant->domain_all == SCOPE_SANDBOX) 495 create_scoped_domain(_metadata, 496 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 497 498 child = fork(); 499 ASSERT_LE(0, child); 500 if (child == 0) { 501 int stream_server_child, dgram_server_child; 502 int pipe_child[2]; 503 pid_t grand_child; 504 505 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 506 507 if (variant->domain_children == OTHER_SANDBOX) 508 create_fs_domain(_metadata); 509 else if (variant->domain_children == SCOPE_SANDBOX) 510 create_scoped_domain( 511 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 512 513 grand_child = fork(); 514 ASSERT_LE(0, grand_child); 515 if (grand_child == 0) { 516 char buf; 517 int stream_err, dgram_err, stream_errno, dgram_errno; 518 int stream_client, dgram_client; 519 520 EXPECT_EQ(0, close(pipe_parent[1])); 521 EXPECT_EQ(0, close(pipe_child[1])); 522 523 if (variant->domain_grand_child == OTHER_SANDBOX) 524 create_fs_domain(_metadata); 525 else if (variant->domain_grand_child == SCOPE_SANDBOX) 526 create_scoped_domain( 527 _metadata, 528 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 529 530 stream_client = socket(AF_UNIX, SOCK_STREAM, 0); 531 ASSERT_LE(0, stream_client); 532 dgram_client = socket(AF_UNIX, SOCK_DGRAM, 0); 533 ASSERT_LE(0, dgram_client); 534 535 ASSERT_EQ(1, read(pipe_child[0], &buf, 1)); 536 stream_err = connect( 537 stream_client, 538 &self->child_stream_address.unix_addr, 539 self->child_stream_address.unix_addr_len); 540 stream_errno = errno; 541 dgram_err = connect( 542 dgram_client, 543 &self->child_dgram_address.unix_addr, 544 self->child_dgram_address.unix_addr_len); 545 dgram_errno = errno; 546 if (can_connect_to_child) { 547 EXPECT_EQ(0, stream_err); 548 EXPECT_EQ(0, dgram_err); 549 } else { 550 EXPECT_EQ(-1, stream_err); 551 EXPECT_EQ(-1, dgram_err); 552 EXPECT_EQ(EPERM, stream_errno); 553 EXPECT_EQ(EPERM, dgram_errno); 554 } 555 556 EXPECT_EQ(0, close(stream_client)); 557 stream_client = socket(AF_UNIX, SOCK_STREAM, 0); 558 ASSERT_LE(0, stream_client); 559 /* Datagram sockets can "reconnect". */ 560 561 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 562 stream_err = connect( 563 stream_client, 564 &self->parent_stream_address.unix_addr, 565 self->parent_stream_address.unix_addr_len); 566 stream_errno = errno; 567 dgram_err = connect( 568 dgram_client, 569 &self->parent_dgram_address.unix_addr, 570 self->parent_dgram_address.unix_addr_len); 571 dgram_errno = errno; 572 if (can_connect_to_parent) { 573 EXPECT_EQ(0, stream_err); 574 EXPECT_EQ(0, dgram_err); 575 } else { 576 EXPECT_EQ(-1, stream_err); 577 EXPECT_EQ(-1, dgram_err); 578 EXPECT_EQ(EPERM, stream_errno); 579 EXPECT_EQ(EPERM, dgram_errno); 580 } 581 EXPECT_EQ(0, close(stream_client)); 582 EXPECT_EQ(0, close(dgram_client)); 583 584 _exit(_metadata->exit_code); 585 return; 586 } 587 EXPECT_EQ(0, close(pipe_child[0])); 588 if (variant->domain_child == OTHER_SANDBOX) 589 create_fs_domain(_metadata); 590 else if (variant->domain_child == SCOPE_SANDBOX) 591 create_scoped_domain( 592 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 593 594 stream_server_child = socket(AF_UNIX, SOCK_STREAM, 0); 595 ASSERT_LE(0, stream_server_child); 596 dgram_server_child = socket(AF_UNIX, SOCK_DGRAM, 0); 597 ASSERT_LE(0, dgram_server_child); 598 599 ASSERT_EQ(0, bind(stream_server_child, 600 &self->child_stream_address.unix_addr, 601 self->child_stream_address.unix_addr_len)); 602 ASSERT_EQ(0, bind(dgram_server_child, 603 &self->child_dgram_address.unix_addr, 604 self->child_dgram_address.unix_addr_len)); 605 ASSERT_EQ(0, listen(stream_server_child, backlog)); 606 607 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 608 ASSERT_EQ(grand_child, waitpid(grand_child, &status, 0)); 609 EXPECT_EQ(0, close(stream_server_child)); 610 EXPECT_EQ(0, close(dgram_server_child)); 611 return; 612 } 613 EXPECT_EQ(0, close(pipe_parent[0])); 614 615 if (variant->domain_parent == OTHER_SANDBOX) 616 create_fs_domain(_metadata); 617 else if (variant->domain_parent == SCOPE_SANDBOX) 618 create_scoped_domain(_metadata, 619 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 620 621 stream_server_parent = socket(AF_UNIX, SOCK_STREAM, 0); 622 ASSERT_LE(0, stream_server_parent); 623 dgram_server_parent = socket(AF_UNIX, SOCK_DGRAM, 0); 624 ASSERT_LE(0, dgram_server_parent); 625 ASSERT_EQ(0, bind(stream_server_parent, 626 &self->parent_stream_address.unix_addr, 627 self->parent_stream_address.unix_addr_len)); 628 ASSERT_EQ(0, bind(dgram_server_parent, 629 &self->parent_dgram_address.unix_addr, 630 self->parent_dgram_address.unix_addr_len)); 631 632 ASSERT_EQ(0, listen(stream_server_parent, backlog)); 633 634 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 635 ASSERT_EQ(child, waitpid(child, &status, 0)); 636 EXPECT_EQ(0, close(stream_server_parent)); 637 EXPECT_EQ(0, close(dgram_server_parent)); 638 639 if (WIFSIGNALED(status) || !WIFEXITED(status) || 640 WEXITSTATUS(status) != EXIT_SUCCESS) 641 _metadata->exit_code = KSFT_FAIL; 642 } 643 644 FIXTURE(outside_socket) 645 { 646 struct service_fixture address, transit_address; 647 }; 648 649 FIXTURE_VARIANT(outside_socket) 650 { 651 const bool child_socket; 652 const int type; 653 }; 654 655 /* clang-format off */ 656 FIXTURE_VARIANT_ADD(outside_socket, allow_dgram_child) { 657 /* clang-format on */ 658 .child_socket = true, 659 .type = SOCK_DGRAM, 660 }; 661 662 /* clang-format off */ 663 FIXTURE_VARIANT_ADD(outside_socket, deny_dgram_server) { 664 /* clang-format on */ 665 .child_socket = false, 666 .type = SOCK_DGRAM, 667 }; 668 669 /* clang-format off */ 670 FIXTURE_VARIANT_ADD(outside_socket, allow_stream_child) { 671 /* clang-format on */ 672 .child_socket = true, 673 .type = SOCK_STREAM, 674 }; 675 676 /* clang-format off */ 677 FIXTURE_VARIANT_ADD(outside_socket, deny_stream_server) { 678 /* clang-format on */ 679 .child_socket = false, 680 .type = SOCK_STREAM, 681 }; 682 683 FIXTURE_SETUP(outside_socket) 684 { 685 drop_caps(_metadata); 686 687 memset(&self->transit_address, 0, sizeof(self->transit_address)); 688 set_unix_address(&self->transit_address, 0); 689 memset(&self->address, 0, sizeof(self->address)); 690 set_unix_address(&self->address, 1); 691 } 692 693 FIXTURE_TEARDOWN(outside_socket) 694 { 695 } 696 697 /* 698 * Test unix_stream_connect and unix_may_send for parent and child processes 699 * when connecting socket has different domain than the process using it. 700 */ 701 TEST_F(outside_socket, socket_with_different_domain) 702 { 703 pid_t child; 704 int err, status; 705 int pipe_child[2], pipe_parent[2]; 706 char buf_parent; 707 int server_socket; 708 709 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 710 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 711 712 child = fork(); 713 ASSERT_LE(0, child); 714 if (child == 0) { 715 int client_socket; 716 char buf_child; 717 718 EXPECT_EQ(0, close(pipe_parent[1])); 719 EXPECT_EQ(0, close(pipe_child[0])); 720 721 /* Client always has a domain. */ 722 create_scoped_domain(_metadata, 723 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 724 725 if (variant->child_socket) { 726 int data_socket, passed_socket, stream_server; 727 728 passed_socket = socket(AF_UNIX, variant->type, 0); 729 ASSERT_LE(0, passed_socket); 730 stream_server = socket(AF_UNIX, SOCK_STREAM, 0); 731 ASSERT_LE(0, stream_server); 732 ASSERT_EQ(0, bind(stream_server, 733 &self->transit_address.unix_addr, 734 self->transit_address.unix_addr_len)); 735 ASSERT_EQ(0, listen(stream_server, backlog)); 736 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 737 data_socket = accept(stream_server, NULL, NULL); 738 ASSERT_LE(0, data_socket); 739 ASSERT_EQ(0, send_fd(data_socket, passed_socket)); 740 EXPECT_EQ(0, close(passed_socket)); 741 EXPECT_EQ(0, close(stream_server)); 742 } 743 744 client_socket = socket(AF_UNIX, variant->type, 0); 745 ASSERT_LE(0, client_socket); 746 747 /* Waits for parent signal for connection. */ 748 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 749 err = connect(client_socket, &self->address.unix_addr, 750 self->address.unix_addr_len); 751 if (variant->child_socket) { 752 EXPECT_EQ(0, err); 753 } else { 754 EXPECT_EQ(-1, err); 755 EXPECT_EQ(EPERM, errno); 756 } 757 EXPECT_EQ(0, close(client_socket)); 758 _exit(_metadata->exit_code); 759 return; 760 } 761 EXPECT_EQ(0, close(pipe_child[1])); 762 EXPECT_EQ(0, close(pipe_parent[0])); 763 764 if (variant->child_socket) { 765 int client_child = socket(AF_UNIX, SOCK_STREAM, 0); 766 767 ASSERT_LE(0, client_child); 768 ASSERT_EQ(1, read(pipe_child[0], &buf_parent, 1)); 769 ASSERT_EQ(0, connect(client_child, 770 &self->transit_address.unix_addr, 771 self->transit_address.unix_addr_len)); 772 server_socket = recv_fd(client_child); 773 EXPECT_EQ(0, close(client_child)); 774 } else { 775 server_socket = socket(AF_UNIX, variant->type, 0); 776 } 777 ASSERT_LE(0, server_socket); 778 779 /* Server always has a domain. */ 780 create_scoped_domain(_metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 781 782 ASSERT_EQ(0, bind(server_socket, &self->address.unix_addr, 783 self->address.unix_addr_len)); 784 if (variant->type == SOCK_STREAM) 785 ASSERT_EQ(0, listen(server_socket, backlog)); 786 787 /* Signals to child that the parent is listening. */ 788 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 789 790 ASSERT_EQ(child, waitpid(child, &status, 0)); 791 EXPECT_EQ(0, close(server_socket)); 792 793 if (WIFSIGNALED(status) || !WIFEXITED(status) || 794 WEXITSTATUS(status) != EXIT_SUCCESS) 795 _metadata->exit_code = KSFT_FAIL; 796 } 797 798 static const char stream_path[] = TMP_DIR "/stream.sock"; 799 static const char dgram_path[] = TMP_DIR "/dgram.sock"; 800 801 /* clang-format off */ 802 FIXTURE(various_address_sockets) {}; 803 /* clang-format on */ 804 805 FIXTURE_VARIANT(various_address_sockets) 806 { 807 const int domain; 808 }; 809 810 /* clang-format off */ 811 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_scoped_domain) { 812 /* clang-format on */ 813 .domain = SCOPE_SANDBOX, 814 }; 815 816 /* clang-format off */ 817 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_other_domain) { 818 /* clang-format on */ 819 .domain = OTHER_SANDBOX, 820 }; 821 822 /* clang-format off */ 823 FIXTURE_VARIANT_ADD(various_address_sockets, pathname_socket_no_domain) { 824 /* clang-format on */ 825 .domain = NO_SANDBOX, 826 }; 827 828 FIXTURE_SETUP(various_address_sockets) 829 { 830 drop_caps(_metadata); 831 832 umask(0077); 833 ASSERT_EQ(0, mkdir(TMP_DIR, 0700)); 834 } 835 836 FIXTURE_TEARDOWN(various_address_sockets) 837 { 838 EXPECT_EQ(0, unlink(stream_path)); 839 EXPECT_EQ(0, unlink(dgram_path)); 840 EXPECT_EQ(0, rmdir(TMP_DIR)); 841 } 842 843 TEST_F(various_address_sockets, scoped_pathname_sockets) 844 { 845 pid_t child; 846 int status; 847 char buf_child, buf_parent; 848 int pipe_parent[2]; 849 int unnamed_sockets[2]; 850 int stream_pathname_socket, dgram_pathname_socket, 851 stream_abstract_socket, dgram_abstract_socket, data_socket; 852 struct service_fixture stream_abstract_addr, dgram_abstract_addr; 853 struct sockaddr_un stream_pathname_addr = { 854 .sun_family = AF_UNIX, 855 }; 856 struct sockaddr_un dgram_pathname_addr = { 857 .sun_family = AF_UNIX, 858 }; 859 860 /* Pathname address. */ 861 snprintf(stream_pathname_addr.sun_path, 862 sizeof(stream_pathname_addr.sun_path), "%s", stream_path); 863 snprintf(dgram_pathname_addr.sun_path, 864 sizeof(dgram_pathname_addr.sun_path), "%s", dgram_path); 865 866 /* Abstract address. */ 867 memset(&stream_abstract_addr, 0, sizeof(stream_abstract_addr)); 868 set_unix_address(&stream_abstract_addr, 0); 869 memset(&dgram_abstract_addr, 0, sizeof(dgram_abstract_addr)); 870 set_unix_address(&dgram_abstract_addr, 1); 871 872 /* Unnamed address for datagram socket. */ 873 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_DGRAM, 0, unnamed_sockets)); 874 875 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 876 877 child = fork(); 878 ASSERT_LE(0, child); 879 if (child == 0) { 880 int err; 881 882 EXPECT_EQ(0, close(pipe_parent[1])); 883 EXPECT_EQ(0, close(unnamed_sockets[1])); 884 885 if (variant->domain == SCOPE_SANDBOX) 886 create_scoped_domain( 887 _metadata, LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 888 else if (variant->domain == OTHER_SANDBOX) 889 create_fs_domain(_metadata); 890 891 /* Waits for parent to listen. */ 892 ASSERT_EQ(1, read(pipe_parent[0], &buf_child, 1)); 893 EXPECT_EQ(0, close(pipe_parent[0])); 894 895 /* Checks that we can send data through a datagram socket. */ 896 ASSERT_EQ(1, write(unnamed_sockets[0], "a", 1)); 897 EXPECT_EQ(0, close(unnamed_sockets[0])); 898 899 /* Connects with pathname sockets. */ 900 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0); 901 ASSERT_LE(0, stream_pathname_socket); 902 ASSERT_EQ(0, 903 connect(stream_pathname_socket, &stream_pathname_addr, 904 sizeof(stream_pathname_addr))); 905 ASSERT_EQ(1, write(stream_pathname_socket, "b", 1)); 906 EXPECT_EQ(0, close(stream_pathname_socket)); 907 908 /* Sends without connection. */ 909 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 910 ASSERT_LE(0, dgram_pathname_socket); 911 err = sendto(dgram_pathname_socket, "c", 1, 0, 912 &dgram_pathname_addr, sizeof(dgram_pathname_addr)); 913 EXPECT_EQ(1, err); 914 915 /* Sends with connection. */ 916 ASSERT_EQ(0, 917 connect(dgram_pathname_socket, &dgram_pathname_addr, 918 sizeof(dgram_pathname_addr))); 919 ASSERT_EQ(1, write(dgram_pathname_socket, "d", 1)); 920 EXPECT_EQ(0, close(dgram_pathname_socket)); 921 922 /* Connects with abstract sockets. */ 923 stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0); 924 ASSERT_LE(0, stream_abstract_socket); 925 err = connect(stream_abstract_socket, 926 &stream_abstract_addr.unix_addr, 927 stream_abstract_addr.unix_addr_len); 928 if (variant->domain == SCOPE_SANDBOX) { 929 EXPECT_EQ(-1, err); 930 EXPECT_EQ(EPERM, errno); 931 } else { 932 EXPECT_EQ(0, err); 933 ASSERT_EQ(1, write(stream_abstract_socket, "e", 1)); 934 } 935 EXPECT_EQ(0, close(stream_abstract_socket)); 936 937 /* Sends without connection. */ 938 dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 939 ASSERT_LE(0, dgram_abstract_socket); 940 err = sendto(dgram_abstract_socket, "f", 1, 0, 941 &dgram_abstract_addr.unix_addr, 942 dgram_abstract_addr.unix_addr_len); 943 if (variant->domain == SCOPE_SANDBOX) { 944 EXPECT_EQ(-1, err); 945 EXPECT_EQ(EPERM, errno); 946 } else { 947 EXPECT_EQ(1, err); 948 } 949 950 /* Sends with connection. */ 951 err = connect(dgram_abstract_socket, 952 &dgram_abstract_addr.unix_addr, 953 dgram_abstract_addr.unix_addr_len); 954 if (variant->domain == SCOPE_SANDBOX) { 955 EXPECT_EQ(-1, err); 956 EXPECT_EQ(EPERM, errno); 957 } else { 958 EXPECT_EQ(0, err); 959 ASSERT_EQ(1, write(dgram_abstract_socket, "g", 1)); 960 } 961 EXPECT_EQ(0, close(dgram_abstract_socket)); 962 963 _exit(_metadata->exit_code); 964 return; 965 } 966 EXPECT_EQ(0, close(pipe_parent[0])); 967 EXPECT_EQ(0, close(unnamed_sockets[0])); 968 969 /* Sets up pathname servers. */ 970 stream_pathname_socket = socket(AF_UNIX, SOCK_STREAM, 0); 971 ASSERT_LE(0, stream_pathname_socket); 972 ASSERT_EQ(0, bind(stream_pathname_socket, &stream_pathname_addr, 973 sizeof(stream_pathname_addr))); 974 ASSERT_EQ(0, listen(stream_pathname_socket, backlog)); 975 976 dgram_pathname_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 977 ASSERT_LE(0, dgram_pathname_socket); 978 ASSERT_EQ(0, bind(dgram_pathname_socket, &dgram_pathname_addr, 979 sizeof(dgram_pathname_addr))); 980 981 /* Sets up abstract servers. */ 982 stream_abstract_socket = socket(AF_UNIX, SOCK_STREAM, 0); 983 ASSERT_LE(0, stream_abstract_socket); 984 ASSERT_EQ(0, 985 bind(stream_abstract_socket, &stream_abstract_addr.unix_addr, 986 stream_abstract_addr.unix_addr_len)); 987 988 dgram_abstract_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 989 ASSERT_LE(0, dgram_abstract_socket); 990 ASSERT_EQ(0, bind(dgram_abstract_socket, &dgram_abstract_addr.unix_addr, 991 dgram_abstract_addr.unix_addr_len)); 992 ASSERT_EQ(0, listen(stream_abstract_socket, backlog)); 993 994 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 995 EXPECT_EQ(0, close(pipe_parent[1])); 996 997 /* Reads from unnamed socket. */ 998 ASSERT_EQ(1, read(unnamed_sockets[1], &buf_parent, sizeof(buf_parent))); 999 ASSERT_EQ('a', buf_parent); 1000 EXPECT_LE(0, close(unnamed_sockets[1])); 1001 1002 /* Reads from pathname sockets. */ 1003 data_socket = accept(stream_pathname_socket, NULL, NULL); 1004 ASSERT_LE(0, data_socket); 1005 ASSERT_EQ(1, read(data_socket, &buf_parent, sizeof(buf_parent))); 1006 ASSERT_EQ('b', buf_parent); 1007 EXPECT_EQ(0, close(data_socket)); 1008 EXPECT_EQ(0, close(stream_pathname_socket)); 1009 1010 ASSERT_EQ(1, 1011 read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent))); 1012 ASSERT_EQ('c', buf_parent); 1013 ASSERT_EQ(1, 1014 read(dgram_pathname_socket, &buf_parent, sizeof(buf_parent))); 1015 ASSERT_EQ('d', buf_parent); 1016 EXPECT_EQ(0, close(dgram_pathname_socket)); 1017 1018 if (variant->domain != SCOPE_SANDBOX) { 1019 /* Reads from abstract sockets if allowed to send. */ 1020 data_socket = accept(stream_abstract_socket, NULL, NULL); 1021 ASSERT_LE(0, data_socket); 1022 ASSERT_EQ(1, 1023 read(data_socket, &buf_parent, sizeof(buf_parent))); 1024 ASSERT_EQ('e', buf_parent); 1025 EXPECT_EQ(0, close(data_socket)); 1026 1027 ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent, 1028 sizeof(buf_parent))); 1029 ASSERT_EQ('f', buf_parent); 1030 ASSERT_EQ(1, read(dgram_abstract_socket, &buf_parent, 1031 sizeof(buf_parent))); 1032 ASSERT_EQ('g', buf_parent); 1033 } 1034 1035 /* Waits for all abstract socket tests. */ 1036 ASSERT_EQ(child, waitpid(child, &status, 0)); 1037 EXPECT_EQ(0, close(stream_abstract_socket)); 1038 EXPECT_EQ(0, close(dgram_abstract_socket)); 1039 1040 if (WIFSIGNALED(status) || !WIFEXITED(status) || 1041 WEXITSTATUS(status) != EXIT_SUCCESS) 1042 _metadata->exit_code = KSFT_FAIL; 1043 } 1044 1045 TEST(datagram_sockets) 1046 { 1047 struct service_fixture connected_addr, non_connected_addr; 1048 int server_conn_socket, server_unconn_socket; 1049 int pipe_parent[2], pipe_child[2]; 1050 int status; 1051 char buf; 1052 pid_t child; 1053 1054 drop_caps(_metadata); 1055 memset(&connected_addr, 0, sizeof(connected_addr)); 1056 set_unix_address(&connected_addr, 0); 1057 memset(&non_connected_addr, 0, sizeof(non_connected_addr)); 1058 set_unix_address(&non_connected_addr, 1); 1059 1060 ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); 1061 ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); 1062 1063 child = fork(); 1064 ASSERT_LE(0, child); 1065 if (child == 0) { 1066 int client_conn_socket, client_unconn_socket; 1067 1068 EXPECT_EQ(0, close(pipe_parent[1])); 1069 EXPECT_EQ(0, close(pipe_child[0])); 1070 1071 client_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1072 client_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1073 ASSERT_LE(0, client_conn_socket); 1074 ASSERT_LE(0, client_unconn_socket); 1075 1076 /* Waits for parent to listen. */ 1077 ASSERT_EQ(1, read(pipe_parent[0], &buf, 1)); 1078 ASSERT_EQ(0, 1079 connect(client_conn_socket, &connected_addr.unix_addr, 1080 connected_addr.unix_addr_len)); 1081 1082 /* 1083 * Both connected and non-connected sockets can send data when 1084 * the domain is not scoped. 1085 */ 1086 ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0)); 1087 ASSERT_EQ(1, sendto(client_unconn_socket, ".", 1, 0, 1088 &non_connected_addr.unix_addr, 1089 non_connected_addr.unix_addr_len)); 1090 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 1091 1092 /* Scopes the domain. */ 1093 create_scoped_domain(_metadata, 1094 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 1095 1096 /* 1097 * Connected socket sends data to the receiver, but the 1098 * non-connected socket must fail to send data. 1099 */ 1100 ASSERT_EQ(1, send(client_conn_socket, ".", 1, 0)); 1101 ASSERT_EQ(-1, sendto(client_unconn_socket, ".", 1, 0, 1102 &non_connected_addr.unix_addr, 1103 non_connected_addr.unix_addr_len)); 1104 ASSERT_EQ(EPERM, errno); 1105 ASSERT_EQ(1, write(pipe_child[1], ".", 1)); 1106 1107 EXPECT_EQ(0, close(client_conn_socket)); 1108 EXPECT_EQ(0, close(client_unconn_socket)); 1109 _exit(_metadata->exit_code); 1110 return; 1111 } 1112 EXPECT_EQ(0, close(pipe_parent[0])); 1113 EXPECT_EQ(0, close(pipe_child[1])); 1114 1115 server_conn_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1116 server_unconn_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1117 ASSERT_LE(0, server_conn_socket); 1118 ASSERT_LE(0, server_unconn_socket); 1119 1120 ASSERT_EQ(0, bind(server_conn_socket, &connected_addr.unix_addr, 1121 connected_addr.unix_addr_len)); 1122 ASSERT_EQ(0, bind(server_unconn_socket, &non_connected_addr.unix_addr, 1123 non_connected_addr.unix_addr_len)); 1124 ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); 1125 1126 /* Waits for child to test. */ 1127 ASSERT_EQ(1, read(pipe_child[0], &buf, 1)); 1128 ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0)); 1129 ASSERT_EQ(1, recv(server_unconn_socket, &buf, 1, 0)); 1130 1131 /* 1132 * Connected datagram socket will receive data, but 1133 * non-connected datagram socket does not receive data. 1134 */ 1135 ASSERT_EQ(1, read(pipe_child[0], &buf, 1)); 1136 ASSERT_EQ(1, recv(server_conn_socket, &buf, 1, 0)); 1137 1138 /* Waits for all tests to finish. */ 1139 ASSERT_EQ(child, waitpid(child, &status, 0)); 1140 EXPECT_EQ(0, close(server_conn_socket)); 1141 EXPECT_EQ(0, close(server_unconn_socket)); 1142 1143 if (WIFSIGNALED(status) || !WIFEXITED(status) || 1144 WEXITSTATUS(status) != EXIT_SUCCESS) 1145 _metadata->exit_code = KSFT_FAIL; 1146 } 1147 1148 TEST(self_connect) 1149 { 1150 struct service_fixture connected_addr, non_connected_addr; 1151 int connected_socket, non_connected_socket, status; 1152 pid_t child; 1153 1154 drop_caps(_metadata); 1155 memset(&connected_addr, 0, sizeof(connected_addr)); 1156 set_unix_address(&connected_addr, 0); 1157 memset(&non_connected_addr, 0, sizeof(non_connected_addr)); 1158 set_unix_address(&non_connected_addr, 1); 1159 1160 connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1161 non_connected_socket = socket(AF_UNIX, SOCK_DGRAM, 0); 1162 ASSERT_LE(0, connected_socket); 1163 ASSERT_LE(0, non_connected_socket); 1164 1165 ASSERT_EQ(0, bind(connected_socket, &connected_addr.unix_addr, 1166 connected_addr.unix_addr_len)); 1167 ASSERT_EQ(0, bind(non_connected_socket, &non_connected_addr.unix_addr, 1168 non_connected_addr.unix_addr_len)); 1169 1170 child = fork(); 1171 ASSERT_LE(0, child); 1172 if (child == 0) { 1173 /* Child's domain is scoped. */ 1174 create_scoped_domain(_metadata, 1175 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 1176 1177 /* 1178 * The child inherits the sockets, and cannot connect or 1179 * send data to them. 1180 */ 1181 ASSERT_EQ(-1, 1182 connect(connected_socket, &connected_addr.unix_addr, 1183 connected_addr.unix_addr_len)); 1184 ASSERT_EQ(EPERM, errno); 1185 1186 ASSERT_EQ(-1, sendto(connected_socket, ".", 1, 0, 1187 &connected_addr.unix_addr, 1188 connected_addr.unix_addr_len)); 1189 ASSERT_EQ(EPERM, errno); 1190 1191 ASSERT_EQ(-1, sendto(non_connected_socket, ".", 1, 0, 1192 &non_connected_addr.unix_addr, 1193 non_connected_addr.unix_addr_len)); 1194 ASSERT_EQ(EPERM, errno); 1195 1196 EXPECT_EQ(0, close(connected_socket)); 1197 EXPECT_EQ(0, close(non_connected_socket)); 1198 _exit(_metadata->exit_code); 1199 return; 1200 } 1201 1202 /* Waits for all tests to finish. */ 1203 ASSERT_EQ(child, waitpid(child, &status, 0)); 1204 EXPECT_EQ(0, close(connected_socket)); 1205 EXPECT_EQ(0, close(non_connected_socket)); 1206 1207 if (WIFSIGNALED(status) || !WIFEXITED(status) || 1208 WEXITSTATUS(status) != EXIT_SUCCESS) 1209 _metadata->exit_code = KSFT_FAIL; 1210 } 1211 1212 /* Trace tests */ 1213 1214 /* clang-format off */ 1215 FIXTURE(trace_unix) { 1216 /* clang-format on */ 1217 int tracefs_ok; 1218 }; 1219 1220 FIXTURE_SETUP(trace_unix) 1221 { 1222 int ret; 1223 1224 set_cap(_metadata, CAP_SYS_ADMIN); 1225 ASSERT_EQ(0, unshare(CLONE_NEWNS)); 1226 ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)); 1227 1228 ret = tracefs_fixture_setup(); 1229 if (ret) { 1230 clear_cap(_metadata, CAP_SYS_ADMIN); 1231 self->tracefs_ok = 0; 1232 SKIP(return, "tracefs not available"); 1233 } 1234 self->tracefs_ok = 1; 1235 1236 ASSERT_EQ(0, tracefs_enable_event( 1237 TRACEFS_DENY_SCOPE_ABSTRACT_UNIX_SOCKET_ENABLE, 1238 true)); 1239 ASSERT_EQ(0, tracefs_clear()); 1240 clear_cap(_metadata, CAP_SYS_ADMIN); 1241 } 1242 1243 FIXTURE_TEARDOWN(trace_unix) 1244 { 1245 if (!self->tracefs_ok) 1246 return; 1247 1248 set_cap(_metadata, CAP_SYS_ADMIN); 1249 tracefs_enable_event(TRACEFS_DENY_SCOPE_ABSTRACT_UNIX_SOCKET_ENABLE, 1250 false); 1251 tracefs_fixture_teardown(); 1252 clear_cap(_metadata, CAP_SYS_ADMIN); 1253 } 1254 1255 /* clang-format off */ 1256 FIXTURE_VARIANT(trace_unix) { 1257 /* clang-format on */ 1258 int sock_type; /* SOCK_STREAM (connect) or SOCK_DGRAM (sendto). */ 1259 bool sandbox; 1260 bool sandbox_target; /* Peer owned by a domain: peer_domain != 0. */ 1261 int expect_denied; 1262 }; 1263 1264 /* clang-format off */ 1265 1266 /* Stream: sandboxed client connect() to an unsandboxed peer (peer_domain=0). */ 1267 FIXTURE_VARIANT_ADD(trace_unix, stream_denied) { 1268 .sock_type = SOCK_STREAM, .sandbox = true, 1269 .sandbox_target = false, .expect_denied = 1, 1270 }; 1271 1272 /* Stream: peer socket owned by a domain, so peer_domain != 0. */ 1273 FIXTURE_VARIANT_ADD(trace_unix, stream_denied_scoped_peer) { 1274 .sock_type = SOCK_STREAM, .sandbox = true, 1275 .sandbox_target = true, .expect_denied = 1, 1276 }; 1277 1278 /* Stream: unsandboxed client, connect() succeeds, no event. */ 1279 FIXTURE_VARIANT_ADD(trace_unix, stream_allowed) { 1280 .sock_type = SOCK_STREAM, .sandbox = false, 1281 .sandbox_target = false, .expect_denied = 0, 1282 }; 1283 1284 /* Datagram: sandboxed client sendto() an unsandboxed peer (peer_domain=0). */ 1285 FIXTURE_VARIANT_ADD(trace_unix, dgram_denied) { 1286 .sock_type = SOCK_DGRAM, .sandbox = true, 1287 .sandbox_target = false, .expect_denied = 1, 1288 }; 1289 1290 /* Datagram: peer socket owned by a domain, so peer_domain != 0. */ 1291 FIXTURE_VARIANT_ADD(trace_unix, dgram_denied_scoped_peer) { 1292 .sock_type = SOCK_DGRAM, .sandbox = true, 1293 .sandbox_target = true, .expect_denied = 1, 1294 }; 1295 1296 /* Datagram: unsandboxed client, sendto() succeeds, no event. */ 1297 FIXTURE_VARIANT_ADD(trace_unix, dgram_allowed) { 1298 .sock_type = SOCK_DGRAM, .sandbox = false, 1299 .sandbox_target = false, .expect_denied = 0, 1300 }; 1301 1302 /* clang-format on */ 1303 1304 /* 1305 * A sandboxed thread reaching an abstract unix socket peer through connect(2) 1306 * (stream) or sendto(2) (datagram) is denied and emits 1307 * landlock_deny_scope_abstract_unix_socket. The abstract name is crafted with 1308 * a space and an embedded NUL followed by an "END" marker to check the 1309 * tracepoint escaping and its length handling (a raw space would break the 1310 * sun_path field regex; strlen() would truncate at the NUL and drop "END"). 1311 * peer_pid is only meaningful for a stream peer (a datagram peer has no 1312 * SO_PEERCRED), so it is asserted only there. 1313 */ 1314 TEST_F(trace_unix, deny_scope_unix) 1315 { 1316 struct sockaddr_un addr = { 1317 .sun_family = AF_UNIX, 1318 }; 1319 char *buf, field[128], expected_pid[16]; 1320 int server_fd, count, status, name_len, addr_len; 1321 pid_t child; 1322 1323 if (!self->tracefs_ok) 1324 SKIP(return, "tracefs not available"); 1325 1326 /* 1327 * For the non-zero peer_domain case, sandbox the parent before it 1328 * creates the server socket, so the socket carries the parent's domain 1329 * and peer_domain= is non-zero. 1330 */ 1331 if (variant->sandbox_target) 1332 create_scoped_domain(_metadata, 1333 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 1334 1335 server_fd = socket(AF_UNIX, variant->sock_type | SOCK_CLOEXEC, 0); 1336 ASSERT_LE(0, server_fd); 1337 1338 addr.sun_path[0] = '\0'; 1339 name_len = snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, 1340 "landlock_trace_test_%d ", getpid()); 1341 addr.sun_path[1 + name_len] = '\0'; 1342 memcpy(addr.sun_path + 1 + name_len + 1, "END", 3); 1343 addr_len = 1344 offsetof(struct sockaddr_un, sun_path) + 1 + name_len + 1 + 3; 1345 1346 ASSERT_EQ(0, bind(server_fd, (struct sockaddr *)&addr, addr_len)); 1347 if (variant->sock_type == SOCK_STREAM) 1348 ASSERT_EQ(0, listen(server_fd, 1)); 1349 1350 child = fork(); 1351 ASSERT_LE(0, child); 1352 1353 if (child == 0) { 1354 int client_fd, ret; 1355 1356 if (variant->sandbox) { 1357 struct landlock_ruleset_attr ruleset_attr = { 1358 .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, 1359 }; 1360 int ruleset_fd; 1361 1362 ruleset_fd = landlock_create_ruleset( 1363 &ruleset_attr, sizeof(ruleset_attr), 0); 1364 if (ruleset_fd < 0) 1365 _exit(1); 1366 1367 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 1368 if (landlock_restrict_self(ruleset_fd, 0)) { 1369 close(ruleset_fd); 1370 _exit(1); 1371 } 1372 close(ruleset_fd); 1373 } 1374 1375 client_fd = 1376 socket(AF_UNIX, variant->sock_type | SOCK_CLOEXEC, 0); 1377 if (client_fd < 0) 1378 _exit(1); 1379 1380 if (variant->sock_type == SOCK_STREAM) 1381 ret = connect(client_fd, (struct sockaddr *)&addr, 1382 addr_len); 1383 else 1384 ret = sendto(client_fd, ".", 1, 0, 1385 (struct sockaddr *)&addr, addr_len); 1386 1387 if (variant->sandbox) { 1388 /* Reaching the peer should be denied. */ 1389 if (ret != -1 || errno != EPERM) { 1390 close(client_fd); 1391 _exit(2); 1392 } 1393 } else { 1394 /* No sandbox: stream connect() == 0, sendto() == 1. */ 1395 int ok = variant->sock_type == SOCK_STREAM ? 0 : 1; 1396 1397 if (ret != ok) { 1398 close(client_fd); 1399 _exit(2); 1400 } 1401 } 1402 close(client_fd); 1403 _exit(0); 1404 } 1405 1406 ASSERT_EQ(child, waitpid(child, &status, 0)); 1407 ASSERT_TRUE(WIFEXITED(status)); 1408 EXPECT_EQ(0, WEXITSTATUS(status)); 1409 close(server_fd); 1410 1411 buf = tracefs_read_buf(); 1412 ASSERT_NE(NULL, buf); 1413 1414 count = tracefs_count_matches( 1415 buf, REGEX_DENY_SCOPE_ABSTRACT_UNIX_SOCKET(TRACE_TASK)); 1416 if (!variant->expect_denied) { 1417 EXPECT_EQ(0, count) 1418 { 1419 TH_LOG("Expected 0 deny_scope events, got %d\n%s", 1420 count, buf); 1421 } 1422 free(buf); 1423 return; 1424 } 1425 1426 EXPECT_EQ(variant->expect_denied, count) 1427 { 1428 TH_LOG("Expected deny_scope_abstract_unix_socket event, " 1429 "got %d\n%s", 1430 count, buf); 1431 } 1432 1433 /* 1434 * sun_path is escaped: a raw space would break this field's [^ ]*$ 1435 * regex, so a successful extract proves the space was escaped, and its 1436 * full length is honored: the "END" marker after the embedded NUL must 1437 * survive (strlen() would truncate it at the NUL). 1438 */ 1439 ASSERT_EQ(0, tracefs_extract_field( 1440 buf, 1441 REGEX_DENY_SCOPE_ABSTRACT_UNIX_SOCKET(TRACE_TASK), 1442 "sun_path", field, sizeof(field))); 1443 EXPECT_NE(NULL, strstr(field, "END")) 1444 { 1445 TH_LOG("sun_path truncated or unescaped: %s", field); 1446 } 1447 1448 /* peer_pid is the parent's PID for a stream peer (0 for datagram). */ 1449 if (variant->sock_type == SOCK_STREAM) { 1450 snprintf(expected_pid, sizeof(expected_pid), "%d", getpid()); 1451 ASSERT_EQ(0, tracefs_extract_field( 1452 buf, 1453 REGEX_DENY_SCOPE_ABSTRACT_UNIX_SOCKET( 1454 TRACE_TASK), 1455 "peer_pid", field, sizeof(field))); 1456 EXPECT_STREQ(expected_pid, field); 1457 } 1458 1459 /* peer_domain: 0 when the peer is unsandboxed, non-zero otherwise. */ 1460 ASSERT_EQ(0, tracefs_extract_field( 1461 buf, 1462 REGEX_DENY_SCOPE_ABSTRACT_UNIX_SOCKET(TRACE_TASK), 1463 "peer_domain", field, sizeof(field))); 1464 EXPECT_EQ(variant->sandbox_target, strcmp("0", field) != 0) 1465 { 1466 TH_LOG("Unexpected peer_domain=%s", field); 1467 } 1468 1469 free(buf); 1470 } 1471 1472 TEST_HARNESS_MAIN 1473