FILE
coredump_socket_test.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/coredump/coredump_socket_test.c
1// SPDX-License-Identifier: GPL-2.0 2 3#include <sys/stat.h> 4#include <sys/epoll.h> 5#include <sys/socket.h> 6#include <sys/un.h> 7 8#include "coredump_test.h" 9 10FIXTURE_SETUP(coredump) 11{ 12 FILE *file; 13 int ret; 14 15 self->pid_coredump_server = -ESRCH; 16 self->fd_tmpfs_detached = -1; 17 file = fopen("/proc/sys/kernel/core_pattern", "r"); 18 ASSERT_NE(NULL, file); 19 20 ret = fread(self->original_core_pattern, 1, sizeof(self->original_core_pattern), file); 21 ASSERT_TRUE(ret || feof(file)); 22 ASSERT_LT(ret, sizeof(self->original_core_pattern)); 23 24 self->original_core_pattern[ret] = '\0'; 25 self->fd_tmpfs_detached = create_detached_tmpfs(); 26 ASSERT_GE(self->fd_tmpfs_detached, 0); 27 28 ret = fclose(file); 29 ASSERT_EQ(0, ret); 30} 31 32FIXTURE_TEARDOWN(coredump) 33{ 34 const char *reason; 35 FILE *file; 36 int ret, status; 37 38 if (self->pid_coredump_server > 0) { 39 kill(self->pid_coredump_server, SIGTERM); 40 waitpid(self->pid_coredump_server, &status, 0); 41 } 42 unlink("/tmp/coredump.file"); 43 unlink("/tmp/coredump.socket"); 44 45 file = fopen("/proc/sys/kernel/core_pattern", "w"); 46 if (!file) { 47 reason = "Unable to open core_pattern"; 48 goto fail; 49 } 50 51 ret = fprintf(file, "%s", self->original_core_pattern); 52 if (ret < 0) { 53 reason = "Unable to write to core_pattern"; 54 goto fail; 55 } 56 57 ret = fclose(file); 58 if (ret) { 59 reason = "Unable to close core_pattern"; 60 goto fail; 61 } 62 63 if (self->fd_tmpfs_detached >= 0) { 64 ret = close(self->fd_tmpfs_detached); 65 if (ret < 0) { 66 reason = "Unable to close detached tmpfs"; 67 goto fail; 68 } 69 self->fd_tmpfs_detached = -1; 70 } 71 72 return; 73fail: 74 /* This should never happen */ 75 fprintf(stderr, "Failed to cleanup coredump test: %s\n", reason); 76} 77 78TEST_F(coredump, socket) 79{ 80 int pidfd, ret, status; 81 pid_t pid, pid_coredump_server; 82 struct stat st; 83 struct pidfd_info info = {}; 84 int ipc_sockets[2]; 85 char c; 86 87 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 88 89 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 90 ASSERT_EQ(ret, 0); 91 92 pid_coredump_server = fork(); 93 ASSERT_GE(pid_coredump_server, 0); 94 if (pid_coredump_server == 0) { 95 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1; 96 int exit_code = EXIT_FAILURE; 97 98 close(ipc_sockets[0]); 99 100 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 101 if (fd_server < 0) { 102 fprintf(stderr, "socket test: create_and_listen_unix_socket failed: %m\n"); 103 goto out; 104 } 105 106 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 107 fprintf(stderr, "socket test: write_nointr to ipc socket failed: %m\n"); 108 goto out; 109 } 110 111 close(ipc_sockets[1]); 112 113 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 114 if (fd_coredump < 0) { 115 fprintf(stderr, "socket test: accept4 failed: %m\n"); 116 goto out; 117 } 118 119 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 120 if (fd_peer_pidfd < 0) { 121 fprintf(stderr, "socket test: get_peer_pidfd failed\n"); 122 goto out; 123 } 124 125 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 126 fprintf(stderr, "socket test: get_pidfd_info failed\n"); 127 goto out; 128 } 129 130 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 131 fprintf(stderr, "socket test: PIDFD_INFO_COREDUMP not set in mask\n"); 132 goto out; 133 } 134 135 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 136 fprintf(stderr, "socket test: PIDFD_COREDUMPED not set in coredump_mask\n"); 137 goto out; 138 } 139 140 fd_core_file = creat("/tmp/coredump.file", 0644); 141 if (fd_core_file < 0) { 142 fprintf(stderr, "socket test: creat coredump file failed: %m\n"); 143 goto out; 144 } 145 146 for (;;) { 147 char buffer[4096]; 148 ssize_t bytes_read, bytes_write; 149 150 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 151 if (bytes_read < 0) { 152 fprintf(stderr, "socket test: read from coredump socket failed: %m\n"); 153 goto out; 154 } 155 156 if (bytes_read == 0) 157 break; 158 159 bytes_write = write(fd_core_file, buffer, bytes_read); 160 if (bytes_read != bytes_write) { 161 if (bytes_write < 0 && errno == ENOSPC) 162 continue; 163 fprintf(stderr, "socket test: write to core file failed (read=%zd, write=%zd): %m\n", bytes_read, bytes_write); 164 goto out; 165 } 166 } 167 168 exit_code = EXIT_SUCCESS; 169 fprintf(stderr, "socket test: completed successfully\n"); 170out: 171 if (fd_core_file >= 0) 172 close(fd_core_file); 173 if (fd_peer_pidfd >= 0) 174 close(fd_peer_pidfd); 175 if (fd_coredump >= 0) 176 close(fd_coredump); 177 if (fd_server >= 0) 178 close(fd_server); 179 _exit(exit_code); 180 } 181 self->pid_coredump_server = pid_coredump_server; 182 183 EXPECT_EQ(close(ipc_sockets[1]), 0); 184 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 185 EXPECT_EQ(close(ipc_sockets[0]), 0); 186 187 pid = fork(); 188 ASSERT_GE(pid, 0); 189 if (pid == 0) 190 crashing_child(); 191 192 pidfd = sys_pidfd_open(pid, 0); 193 ASSERT_GE(pidfd, 0); 194 195 waitpid(pid, &status, 0); 196 ASSERT_TRUE(WIFSIGNALED(status)); 197 ASSERT_TRUE(WCOREDUMP(status)); 198 199 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 200 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 201 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 202 203 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 204 205 ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); 206 ASSERT_GT(st.st_size, 0); 207} 208 209TEST_F(coredump, socket_detect_userspace_client) 210{ 211 int pidfd, ret, status; 212 pid_t pid, pid_coredump_server; 213 struct stat st; 214 struct pidfd_info info = { 215 .mask = PIDFD_INFO_COREDUMP, 216 }; 217 int ipc_sockets[2]; 218 char c; 219 220 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 221 222 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 223 ASSERT_EQ(ret, 0); 224 225 pid_coredump_server = fork(); 226 ASSERT_GE(pid_coredump_server, 0); 227 if (pid_coredump_server == 0) { 228 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 229 int exit_code = EXIT_FAILURE; 230 231 close(ipc_sockets[0]); 232 233 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 234 if (fd_server < 0) { 235 fprintf(stderr, "socket_detect_userspace_client: create_and_listen_unix_socket failed: %m\n"); 236 goto out; 237 } 238 239 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 240 fprintf(stderr, "socket_detect_userspace_client: write_nointr to ipc socket failed: %m\n"); 241 goto out; 242 } 243 244 close(ipc_sockets[1]); 245 246 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 247 if (fd_coredump < 0) { 248 fprintf(stderr, "socket_detect_userspace_client: accept4 failed: %m\n"); 249 goto out; 250 } 251 252 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 253 if (fd_peer_pidfd < 0) { 254 fprintf(stderr, "socket_detect_userspace_client: get_peer_pidfd failed\n"); 255 goto out; 256 } 257 258 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 259 fprintf(stderr, "socket_detect_userspace_client: get_pidfd_info failed\n"); 260 goto out; 261 } 262 263 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 264 fprintf(stderr, "socket_detect_userspace_client: PIDFD_INFO_COREDUMP not set in mask\n"); 265 goto out; 266 } 267 268 if (info.coredump_mask & PIDFD_COREDUMPED) { 269 fprintf(stderr, "socket_detect_userspace_client: PIDFD_COREDUMPED incorrectly set (should be userspace client)\n"); 270 goto out; 271 } 272 273 exit_code = EXIT_SUCCESS; 274 fprintf(stderr, "socket_detect_userspace_client: completed successfully\n"); 275out: 276 if (fd_peer_pidfd >= 0) 277 close(fd_peer_pidfd); 278 if (fd_coredump >= 0) 279 close(fd_coredump); 280 if (fd_server >= 0) 281 close(fd_server); 282 _exit(exit_code); 283 } 284 self->pid_coredump_server = pid_coredump_server; 285 286 EXPECT_EQ(close(ipc_sockets[1]), 0); 287 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 288 EXPECT_EQ(close(ipc_sockets[0]), 0); 289 290 pid = fork(); 291 ASSERT_GE(pid, 0); 292 if (pid == 0) { 293 int fd_socket; 294 ssize_t ret; 295 const struct sockaddr_un coredump_sk = { 296 .sun_family = AF_UNIX, 297 .sun_path = "/tmp/coredump.socket", 298 }; 299 size_t coredump_sk_len = 300 offsetof(struct sockaddr_un, sun_path) + 301 sizeof("/tmp/coredump.socket"); 302 303 fd_socket = socket(AF_UNIX, SOCK_STREAM, 0); 304 if (fd_socket < 0) { 305 fprintf(stderr, "socket_detect_userspace_client (client): socket failed: %m\n"); 306 _exit(EXIT_FAILURE); 307 } 308 309 ret = connect(fd_socket, (const struct sockaddr *)&coredump_sk, coredump_sk_len); 310 if (ret < 0) { 311 fprintf(stderr, "socket_detect_userspace_client (client): connect failed: %m\n"); 312 _exit(EXIT_FAILURE); 313 } 314 315 close(fd_socket); 316 pause(); 317 fprintf(stderr, "socket_detect_userspace_client (client): completed successfully\n"); 318 _exit(EXIT_SUCCESS); 319 } 320 321 pidfd = sys_pidfd_open(pid, 0); 322 ASSERT_GE(pidfd, 0); 323 324 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 325 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 326 ASSERT_EQ((info.coredump_mask & PIDFD_COREDUMPED), 0); 327 328 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 329 330 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0); 331 ASSERT_EQ(close(pidfd), 0); 332 333 waitpid(pid, &status, 0); 334 ASSERT_TRUE(WIFSIGNALED(status)); 335 ASSERT_EQ(WTERMSIG(status), SIGKILL); 336 337 ASSERT_NE(stat("/tmp/coredump.file", &st), 0); 338 ASSERT_EQ(errno, ENOENT); 339} 340 341TEST_F(coredump, socket_enoent) 342{ 343 int pidfd, status; 344 pid_t pid; 345 346 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 347 348 pid = fork(); 349 ASSERT_GE(pid, 0); 350 if (pid == 0) 351 crashing_child(); 352 353 pidfd = sys_pidfd_open(pid, 0); 354 ASSERT_GE(pidfd, 0); 355 356 waitpid(pid, &status, 0); 357 ASSERT_TRUE(WIFSIGNALED(status)); 358 ASSERT_FALSE(WCOREDUMP(status)); 359} 360 361TEST_F(coredump, socket_no_listener) 362{ 363 int pidfd, ret, status; 364 pid_t pid, pid_coredump_server; 365 int ipc_sockets[2]; 366 char c; 367 const struct sockaddr_un coredump_sk = { 368 .sun_family = AF_UNIX, 369 .sun_path = "/tmp/coredump.socket", 370 }; 371 size_t coredump_sk_len = offsetof(struct sockaddr_un, sun_path) + 372 sizeof("/tmp/coredump.socket"); 373 374 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 375 376 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 377 ASSERT_EQ(ret, 0); 378 379 pid_coredump_server = fork(); 380 ASSERT_GE(pid_coredump_server, 0); 381 if (pid_coredump_server == 0) { 382 int fd_server = -1; 383 int exit_code = EXIT_FAILURE; 384 385 close(ipc_sockets[0]); 386 387 fd_server = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 388 if (fd_server < 0) { 389 fprintf(stderr, "socket_no_listener: socket failed: %m\n"); 390 goto out; 391 } 392 393 ret = bind(fd_server, (const struct sockaddr *)&coredump_sk, coredump_sk_len); 394 if (ret < 0) { 395 fprintf(stderr, "socket_no_listener: bind failed: %m\n"); 396 goto out; 397 } 398 399 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 400 fprintf(stderr, "socket_no_listener: write_nointr to ipc socket failed: %m\n"); 401 goto out; 402 } 403 404 exit_code = EXIT_SUCCESS; 405 fprintf(stderr, "socket_no_listener: completed successfully\n"); 406out: 407 if (fd_server >= 0) 408 close(fd_server); 409 close(ipc_sockets[1]); 410 _exit(exit_code); 411 } 412 self->pid_coredump_server = pid_coredump_server; 413 414 EXPECT_EQ(close(ipc_sockets[1]), 0); 415 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 416 EXPECT_EQ(close(ipc_sockets[0]), 0); 417 418 pid = fork(); 419 ASSERT_GE(pid, 0); 420 if (pid == 0) 421 crashing_child(); 422 423 pidfd = sys_pidfd_open(pid, 0); 424 ASSERT_GE(pidfd, 0); 425 426 waitpid(pid, &status, 0); 427 ASSERT_TRUE(WIFSIGNALED(status)); 428 ASSERT_FALSE(WCOREDUMP(status)); 429 430 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 431} 432 433/* 434 * Test: PIDFD_INFO_COREDUMP_SIGNAL via simple socket coredump 435 * 436 * Verify that when using simple socket-based coredump (@ pattern), 437 * the coredump_signal field is correctly exposed as SIGSEGV. 438 */ 439TEST_F(coredump, socket_coredump_signal_sigsegv) 440{ 441 int pidfd, ret, status; 442 pid_t pid, pid_coredump_server; 443 struct pidfd_info info = {}; 444 int ipc_sockets[2]; 445 char c; 446 447 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 448 449 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 450 ASSERT_EQ(ret, 0); 451 452 pid_coredump_server = fork(); 453 ASSERT_GE(pid_coredump_server, 0); 454 if (pid_coredump_server == 0) { 455 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1; 456 int exit_code = EXIT_FAILURE; 457 458 close(ipc_sockets[0]); 459 460 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 461 if (fd_server < 0) { 462 fprintf(stderr, "socket_coredump_signal_sigsegv: create_and_listen_unix_socket failed: %m\n"); 463 goto out; 464 } 465 466 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 467 fprintf(stderr, "socket_coredump_signal_sigsegv: write_nointr to ipc socket failed: %m\n"); 468 goto out; 469 } 470 471 close(ipc_sockets[1]); 472 473 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 474 if (fd_coredump < 0) { 475 fprintf(stderr, "socket_coredump_signal_sigsegv: accept4 failed: %m\n"); 476 goto out; 477 } 478 479 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 480 if (fd_peer_pidfd < 0) { 481 fprintf(stderr, "socket_coredump_signal_sigsegv: get_peer_pidfd failed\n"); 482 goto out; 483 } 484 485 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 486 fprintf(stderr, "socket_coredump_signal_sigsegv: get_pidfd_info failed\n"); 487 goto out; 488 } 489 490 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 491 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP not set in mask\n"); 492 goto out; 493 } 494 495 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 496 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_COREDUMPED not set in coredump_mask\n"); 497 goto out; 498 } 499 500 /* Verify coredump_signal is available and correct */ 501 if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { 502 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_SIGNAL not set in mask\n"); 503 goto out; 504 } 505 506 if (info.coredump_signal != SIGSEGV) { 507 fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_signal=%d, expected SIGSEGV=%d\n", 508 info.coredump_signal, SIGSEGV); 509 goto out; 510 } 511 512 fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached); 513 if (fd_core_file < 0) { 514 fprintf(stderr, "socket_coredump_signal_sigsegv: open_coredump_tmpfile failed: %m\n"); 515 goto out; 516 } 517 518 for (;;) { 519 char buffer[4096]; 520 ssize_t bytes_read, bytes_write; 521 522 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 523 if (bytes_read < 0) { 524 fprintf(stderr, "socket_coredump_signal_sigsegv: read from coredump socket failed: %m\n"); 525 goto out; 526 } 527 528 if (bytes_read == 0) 529 break; 530 531 bytes_write = write(fd_core_file, buffer, bytes_read); 532 if (bytes_read != bytes_write) { 533 fprintf(stderr, "socket_coredump_signal_sigsegv: write to core file failed (read=%zd, write=%zd): %m\n", 534 bytes_read, bytes_write); 535 goto out; 536 } 537 } 538 539 exit_code = EXIT_SUCCESS; 540 fprintf(stderr, "socket_coredump_signal_sigsegv: completed successfully\n"); 541out: 542 if (fd_core_file >= 0) 543 close(fd_core_file); 544 if (fd_peer_pidfd >= 0) 545 close(fd_peer_pidfd); 546 if (fd_coredump >= 0) 547 close(fd_coredump); 548 if (fd_server >= 0) 549 close(fd_server); 550 _exit(exit_code); 551 } 552 self->pid_coredump_server = pid_coredump_server; 553 554 EXPECT_EQ(close(ipc_sockets[1]), 0); 555 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 556 EXPECT_EQ(close(ipc_sockets[0]), 0); 557 558 pid = fork(); 559 ASSERT_GE(pid, 0); 560 if (pid == 0) 561 crashing_child(); 562 563 pidfd = sys_pidfd_open(pid, 0); 564 ASSERT_GE(pidfd, 0); 565 566 waitpid(pid, &status, 0); 567 ASSERT_TRUE(WIFSIGNALED(status)); 568 ASSERT_EQ(WTERMSIG(status), SIGSEGV); 569 ASSERT_TRUE(WCOREDUMP(status)); 570 571 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 572 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); 573 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); 574 ASSERT_EQ(info.coredump_signal, SIGSEGV); 575 576 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 577} 578 579/* 580 * Test: PIDFD_INFO_COREDUMP_SIGNAL via simple socket coredump with SIGABRT 581 * 582 * Verify that when using simple socket-based coredump (@ pattern), 583 * the coredump_signal field is correctly exposed as SIGABRT. 584 */ 585TEST_F(coredump, socket_coredump_signal_sigabrt) 586{ 587 int pidfd, ret, status; 588 pid_t pid, pid_coredump_server; 589 struct pidfd_info info = {}; 590 int ipc_sockets[2]; 591 char c; 592 593 ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket")); 594 595 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 596 ASSERT_EQ(ret, 0); 597 598 pid_coredump_server = fork(); 599 ASSERT_GE(pid_coredump_server, 0); 600 if (pid_coredump_server == 0) { 601 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1; 602 int exit_code = EXIT_FAILURE; 603 604 close(ipc_sockets[0]); 605 606 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 607 if (fd_server < 0) { 608 fprintf(stderr, "socket_coredump_signal_sigabrt: create_and_listen_unix_socket failed: %m\n"); 609 goto out; 610 } 611 612 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 613 fprintf(stderr, "socket_coredump_signal_sigabrt: write_nointr to ipc socket failed: %m\n"); 614 goto out; 615 } 616 617 close(ipc_sockets[1]); 618 619 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 620 if (fd_coredump < 0) { 621 fprintf(stderr, "socket_coredump_signal_sigabrt: accept4 failed: %m\n"); 622 goto out; 623 } 624 625 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 626 if (fd_peer_pidfd < 0) { 627 fprintf(stderr, "socket_coredump_signal_sigabrt: get_peer_pidfd failed\n"); 628 goto out; 629 } 630 631 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 632 fprintf(stderr, "socket_coredump_signal_sigabrt: get_pidfd_info failed\n"); 633 goto out; 634 } 635 636 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 637 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP not set in mask\n"); 638 goto out; 639 } 640 641 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 642 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_COREDUMPED not set in coredump_mask\n"); 643 goto out; 644 } 645 646 /* Verify coredump_signal is available and correct */ 647 if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { 648 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_SIGNAL not set in mask\n"); 649 goto out; 650 } 651 652 if (info.coredump_signal != SIGABRT) { 653 fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_signal=%d, expected SIGABRT=%d\n", 654 info.coredump_signal, SIGABRT); 655 goto out; 656 } 657 658 fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached); 659 if (fd_core_file < 0) { 660 fprintf(stderr, "socket_coredump_signal_sigabrt: open_coredump_tmpfile failed: %m\n"); 661 goto out; 662 } 663 664 for (;;) { 665 char buffer[4096]; 666 ssize_t bytes_read, bytes_write; 667 668 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 669 if (bytes_read < 0) { 670 fprintf(stderr, "socket_coredump_signal_sigabrt: read from coredump socket failed: %m\n"); 671 goto out; 672 } 673 674 if (bytes_read == 0) 675 break; 676 677 bytes_write = write(fd_core_file, buffer, bytes_read); 678 if (bytes_read != bytes_write) { 679 fprintf(stderr, "socket_coredump_signal_sigabrt: write to core file failed (read=%zd, write=%zd): %m\n", 680 bytes_read, bytes_write); 681 goto out; 682 } 683 } 684 685 exit_code = EXIT_SUCCESS; 686 fprintf(stderr, "socket_coredump_signal_sigabrt: completed successfully\n"); 687out: 688 if (fd_core_file >= 0) 689 close(fd_core_file); 690 if (fd_peer_pidfd >= 0) 691 close(fd_peer_pidfd); 692 if (fd_coredump >= 0) 693 close(fd_coredump); 694 if (fd_server >= 0) 695 close(fd_server); 696 _exit(exit_code); 697 } 698 self->pid_coredump_server = pid_coredump_server; 699 700 EXPECT_EQ(close(ipc_sockets[1]), 0); 701 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 702 EXPECT_EQ(close(ipc_sockets[0]), 0); 703 704 pid = fork(); 705 ASSERT_GE(pid, 0); 706 if (pid == 0) 707 abort(); 708 709 pidfd = sys_pidfd_open(pid, 0); 710 ASSERT_GE(pidfd, 0); 711 712 waitpid(pid, &status, 0); 713 ASSERT_TRUE(WIFSIGNALED(status)); 714 ASSERT_EQ(WTERMSIG(status), SIGABRT); 715 ASSERT_TRUE(WCOREDUMP(status)); 716 717 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 718 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); 719 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); 720 ASSERT_EQ(info.coredump_signal, SIGABRT); 721 722 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 723} 724 725TEST_F(coredump, socket_invalid_paths) 726{ 727 ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket")); 728 ASSERT_FALSE(set_core_pattern("@/tmp/../coredump.socket")); 729 ASSERT_FALSE(set_core_pattern("@../coredump.socket")); 730 ASSERT_FALSE(set_core_pattern("@/tmp/coredump.socket/..")); 731 ASSERT_FALSE(set_core_pattern("@..")); 732 733 ASSERT_FALSE(set_core_pattern("@@ /tmp/coredump.socket")); 734 ASSERT_FALSE(set_core_pattern("@@/tmp/../coredump.socket")); 735 ASSERT_FALSE(set_core_pattern("@@../coredump.socket")); 736 ASSERT_FALSE(set_core_pattern("@@/tmp/coredump.socket/..")); 737 ASSERT_FALSE(set_core_pattern("@@..")); 738 739 ASSERT_FALSE(set_core_pattern("@@@/tmp/coredump.socket")); 740} 741 742TEST_HARNESS_MAIN
~/
Read-only file preview.