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 10 #define NUM_CRASHING_COREDUMPS 5 11 12 FIXTURE_SETUP(coredump) 13 { 14 FILE *file; 15 int ret; 16 17 self->pid_coredump_server = -ESRCH; 18 self->fd_tmpfs_detached = -1; 19 file = fopen("/proc/sys/kernel/core_pattern", "r"); 20 ASSERT_NE(NULL, file); 21 22 ret = fread(self->original_core_pattern, 1, sizeof(self->original_core_pattern), file); 23 ASSERT_TRUE(ret || feof(file)); 24 ASSERT_LT(ret, sizeof(self->original_core_pattern)); 25 26 self->original_core_pattern[ret] = '\0'; 27 self->fd_tmpfs_detached = create_detached_tmpfs(); 28 ASSERT_GE(self->fd_tmpfs_detached, 0); 29 30 ret = fclose(file); 31 ASSERT_EQ(0, ret); 32 } 33 34 FIXTURE_TEARDOWN(coredump) 35 { 36 const char *reason; 37 FILE *file; 38 int ret, status; 39 40 if (self->pid_coredump_server > 0) { 41 kill(self->pid_coredump_server, SIGTERM); 42 waitpid(self->pid_coredump_server, &status, 0); 43 } 44 unlink("/tmp/coredump.file"); 45 unlink("/tmp/coredump.socket"); 46 47 file = fopen("/proc/sys/kernel/core_pattern", "w"); 48 if (!file) { 49 reason = "Unable to open core_pattern"; 50 goto fail; 51 } 52 53 ret = fprintf(file, "%s", self->original_core_pattern); 54 if (ret < 0) { 55 reason = "Unable to write to core_pattern"; 56 goto fail; 57 } 58 59 ret = fclose(file); 60 if (ret) { 61 reason = "Unable to close core_pattern"; 62 goto fail; 63 } 64 65 if (self->fd_tmpfs_detached >= 0) { 66 ret = close(self->fd_tmpfs_detached); 67 if (ret < 0) { 68 reason = "Unable to close detached tmpfs"; 69 goto fail; 70 } 71 self->fd_tmpfs_detached = -1; 72 } 73 74 return; 75 fail: 76 /* This should never happen */ 77 fprintf(stderr, "Failed to cleanup coredump test: %s\n", reason); 78 } 79 80 TEST_F(coredump, socket_request_kernel) 81 { 82 int pidfd, ret, status; 83 pid_t pid, pid_coredump_server; 84 struct stat st; 85 struct pidfd_info info = {}; 86 int ipc_sockets[2]; 87 char c; 88 89 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 90 91 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 92 ASSERT_EQ(ret, 0); 93 94 pid_coredump_server = fork(); 95 ASSERT_GE(pid_coredump_server, 0); 96 if (pid_coredump_server == 0) { 97 struct coredump_req req = {}; 98 int fd_server = -1, fd_coredump = -1, fd_core_file = -1, fd_peer_pidfd = -1; 99 int exit_code = EXIT_FAILURE; 100 101 close(ipc_sockets[0]); 102 103 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 104 if (fd_server < 0) { 105 fprintf(stderr, "socket_request_kernel: create_and_listen_unix_socket failed: %m\n"); 106 goto out; 107 } 108 109 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 110 fprintf(stderr, "socket_request_kernel: write_nointr to ipc socket failed: %m\n"); 111 goto out; 112 } 113 114 close(ipc_sockets[1]); 115 116 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 117 if (fd_coredump < 0) { 118 fprintf(stderr, "socket_request_kernel: accept4 failed: %m\n"); 119 goto out; 120 } 121 122 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 123 if (fd_peer_pidfd < 0) { 124 fprintf(stderr, "socket_request_kernel: get_peer_pidfd failed\n"); 125 goto out; 126 } 127 128 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 129 fprintf(stderr, "socket_request_kernel: get_pidfd_info failed\n"); 130 goto out; 131 } 132 133 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 134 fprintf(stderr, "socket_request_kernel: PIDFD_INFO_COREDUMP not set in mask\n"); 135 goto out; 136 } 137 138 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 139 fprintf(stderr, "socket_request_kernel: PIDFD_COREDUMPED not set in coredump_mask\n"); 140 goto out; 141 } 142 143 fd_core_file = creat("/tmp/coredump.file", 0644); 144 if (fd_core_file < 0) { 145 fprintf(stderr, "socket_request_kernel: creat coredump file failed: %m\n"); 146 goto out; 147 } 148 149 if (!read_coredump_req(fd_coredump, &req)) { 150 fprintf(stderr, "socket_request_kernel: read_coredump_req failed\n"); 151 goto out; 152 } 153 154 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 155 COREDUMP_KERNEL | COREDUMP_USERSPACE | 156 COREDUMP_REJECT | COREDUMP_WAIT)) { 157 fprintf(stderr, "socket_request_kernel: check_coredump_req failed\n"); 158 goto out; 159 } 160 161 if (!send_coredump_ack(fd_coredump, &req, 162 COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { 163 fprintf(stderr, "socket_request_kernel: send_coredump_ack failed\n"); 164 goto out; 165 } 166 167 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 168 fprintf(stderr, "socket_request_kernel: read_marker COREDUMP_MARK_REQACK failed\n"); 169 goto out; 170 } 171 172 for (;;) { 173 char buffer[4096]; 174 ssize_t bytes_read, bytes_write; 175 176 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 177 if (bytes_read < 0) { 178 fprintf(stderr, "socket_request_kernel: read from coredump socket failed: %m\n"); 179 goto out; 180 } 181 182 if (bytes_read == 0) 183 break; 184 185 bytes_write = write(fd_core_file, buffer, bytes_read); 186 if (bytes_read != bytes_write) { 187 if (bytes_write < 0 && errno == ENOSPC) 188 continue; 189 fprintf(stderr, "socket_request_kernel: write to core file failed (read=%zd, write=%zd): %m\n", 190 bytes_read, bytes_write); 191 goto out; 192 } 193 } 194 195 exit_code = EXIT_SUCCESS; 196 fprintf(stderr, "socket_request_kernel: completed successfully\n"); 197 out: 198 if (fd_core_file >= 0) 199 close(fd_core_file); 200 if (fd_peer_pidfd >= 0) 201 close(fd_peer_pidfd); 202 if (fd_coredump >= 0) 203 close(fd_coredump); 204 if (fd_server >= 0) 205 close(fd_server); 206 _exit(exit_code); 207 } 208 self->pid_coredump_server = pid_coredump_server; 209 210 EXPECT_EQ(close(ipc_sockets[1]), 0); 211 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 212 EXPECT_EQ(close(ipc_sockets[0]), 0); 213 214 pid = fork(); 215 ASSERT_GE(pid, 0); 216 if (pid == 0) 217 crashing_child(); 218 219 pidfd = sys_pidfd_open(pid, 0); 220 ASSERT_GE(pidfd, 0); 221 222 waitpid(pid, &status, 0); 223 ASSERT_TRUE(WIFSIGNALED(status)); 224 ASSERT_TRUE(WCOREDUMP(status)); 225 226 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 227 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 228 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 229 230 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 231 232 ASSERT_EQ(stat("/tmp/coredump.file", &st), 0); 233 ASSERT_GT(st.st_size, 0); 234 system("file /tmp/coredump.file"); 235 } 236 237 TEST_F(coredump, socket_request_userspace) 238 { 239 int pidfd, ret, status; 240 pid_t pid, pid_coredump_server; 241 struct pidfd_info info = {}; 242 int ipc_sockets[2]; 243 char c; 244 245 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 246 247 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 248 ASSERT_EQ(ret, 0); 249 250 pid_coredump_server = fork(); 251 ASSERT_GE(pid_coredump_server, 0); 252 if (pid_coredump_server == 0) { 253 struct coredump_req req = {}; 254 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 255 int exit_code = EXIT_FAILURE; 256 257 close(ipc_sockets[0]); 258 259 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 260 if (fd_server < 0) { 261 fprintf(stderr, "socket_request_userspace: create_and_listen_unix_socket failed: %m\n"); 262 goto out; 263 } 264 265 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 266 fprintf(stderr, "socket_request_userspace: write_nointr to ipc socket failed: %m\n"); 267 goto out; 268 } 269 270 close(ipc_sockets[1]); 271 272 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 273 if (fd_coredump < 0) { 274 fprintf(stderr, "socket_request_userspace: accept4 failed: %m\n"); 275 goto out; 276 } 277 278 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 279 if (fd_peer_pidfd < 0) { 280 fprintf(stderr, "socket_request_userspace: get_peer_pidfd failed\n"); 281 goto out; 282 } 283 284 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 285 fprintf(stderr, "socket_request_userspace: get_pidfd_info failed\n"); 286 goto out; 287 } 288 289 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 290 fprintf(stderr, "socket_request_userspace: PIDFD_INFO_COREDUMP not set in mask\n"); 291 goto out; 292 } 293 294 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 295 fprintf(stderr, "socket_request_userspace: PIDFD_COREDUMPED not set in coredump_mask\n"); 296 goto out; 297 } 298 299 if (!read_coredump_req(fd_coredump, &req)) { 300 fprintf(stderr, "socket_request_userspace: read_coredump_req failed\n"); 301 goto out; 302 } 303 304 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 305 COREDUMP_KERNEL | COREDUMP_USERSPACE | 306 COREDUMP_REJECT | COREDUMP_WAIT)) { 307 fprintf(stderr, "socket_request_userspace: check_coredump_req failed\n"); 308 goto out; 309 } 310 311 if (!send_coredump_ack(fd_coredump, &req, 312 COREDUMP_USERSPACE | COREDUMP_WAIT, 0)) { 313 fprintf(stderr, "socket_request_userspace: send_coredump_ack failed\n"); 314 goto out; 315 } 316 317 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 318 fprintf(stderr, "socket_request_userspace: read_marker COREDUMP_MARK_REQACK failed\n"); 319 goto out; 320 } 321 322 for (;;) { 323 char buffer[4096]; 324 ssize_t bytes_read; 325 326 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 327 if (bytes_read > 0) { 328 fprintf(stderr, "socket_request_userspace: unexpected data received (expected no coredump data)\n"); 329 goto out; 330 } 331 332 if (bytes_read < 0) { 333 fprintf(stderr, "socket_request_userspace: read from coredump socket failed: %m\n"); 334 goto out; 335 } 336 337 if (bytes_read == 0) 338 break; 339 } 340 341 exit_code = EXIT_SUCCESS; 342 fprintf(stderr, "socket_request_userspace: completed successfully\n"); 343 out: 344 if (fd_peer_pidfd >= 0) 345 close(fd_peer_pidfd); 346 if (fd_coredump >= 0) 347 close(fd_coredump); 348 if (fd_server >= 0) 349 close(fd_server); 350 _exit(exit_code); 351 } 352 self->pid_coredump_server = pid_coredump_server; 353 354 EXPECT_EQ(close(ipc_sockets[1]), 0); 355 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 356 EXPECT_EQ(close(ipc_sockets[0]), 0); 357 358 pid = fork(); 359 ASSERT_GE(pid, 0); 360 if (pid == 0) 361 crashing_child(); 362 363 pidfd = sys_pidfd_open(pid, 0); 364 ASSERT_GE(pidfd, 0); 365 366 waitpid(pid, &status, 0); 367 ASSERT_TRUE(WIFSIGNALED(status)); 368 ASSERT_TRUE(WCOREDUMP(status)); 369 370 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 371 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 372 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 373 374 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 375 } 376 377 TEST_F(coredump, socket_request_reject) 378 { 379 int pidfd, ret, status; 380 pid_t pid, pid_coredump_server; 381 struct pidfd_info info = {}; 382 int ipc_sockets[2]; 383 char c; 384 385 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 386 387 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 388 ASSERT_EQ(ret, 0); 389 390 pid_coredump_server = fork(); 391 ASSERT_GE(pid_coredump_server, 0); 392 if (pid_coredump_server == 0) { 393 struct coredump_req req = {}; 394 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 395 int exit_code = EXIT_FAILURE; 396 397 close(ipc_sockets[0]); 398 399 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 400 if (fd_server < 0) { 401 fprintf(stderr, "socket_request_reject: create_and_listen_unix_socket failed: %m\n"); 402 goto out; 403 } 404 405 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 406 fprintf(stderr, "socket_request_reject: write_nointr to ipc socket failed: %m\n"); 407 goto out; 408 } 409 410 close(ipc_sockets[1]); 411 412 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 413 if (fd_coredump < 0) { 414 fprintf(stderr, "socket_request_reject: accept4 failed: %m\n"); 415 goto out; 416 } 417 418 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 419 if (fd_peer_pidfd < 0) { 420 fprintf(stderr, "socket_request_reject: get_peer_pidfd failed\n"); 421 goto out; 422 } 423 424 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 425 fprintf(stderr, "socket_request_reject: get_pidfd_info failed\n"); 426 goto out; 427 } 428 429 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 430 fprintf(stderr, "socket_request_reject: PIDFD_INFO_COREDUMP not set in mask\n"); 431 goto out; 432 } 433 434 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 435 fprintf(stderr, "socket_request_reject: PIDFD_COREDUMPED not set in coredump_mask\n"); 436 goto out; 437 } 438 439 if (!read_coredump_req(fd_coredump, &req)) { 440 fprintf(stderr, "socket_request_reject: read_coredump_req failed\n"); 441 goto out; 442 } 443 444 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 445 COREDUMP_KERNEL | COREDUMP_USERSPACE | 446 COREDUMP_REJECT | COREDUMP_WAIT)) { 447 fprintf(stderr, "socket_request_reject: check_coredump_req failed\n"); 448 goto out; 449 } 450 451 if (!send_coredump_ack(fd_coredump, &req, 452 COREDUMP_REJECT | COREDUMP_WAIT, 0)) { 453 fprintf(stderr, "socket_request_reject: send_coredump_ack failed\n"); 454 goto out; 455 } 456 457 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 458 fprintf(stderr, "socket_request_reject: read_marker COREDUMP_MARK_REQACK failed\n"); 459 goto out; 460 } 461 462 for (;;) { 463 char buffer[4096]; 464 ssize_t bytes_read; 465 466 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 467 if (bytes_read > 0) { 468 fprintf(stderr, "socket_request_reject: unexpected data received (expected no coredump data for REJECT)\n"); 469 goto out; 470 } 471 472 if (bytes_read < 0) { 473 fprintf(stderr, "socket_request_reject: read from coredump socket failed: %m\n"); 474 goto out; 475 } 476 477 if (bytes_read == 0) 478 break; 479 } 480 481 exit_code = EXIT_SUCCESS; 482 fprintf(stderr, "socket_request_reject: completed successfully\n"); 483 out: 484 if (fd_peer_pidfd >= 0) 485 close(fd_peer_pidfd); 486 if (fd_coredump >= 0) 487 close(fd_coredump); 488 if (fd_server >= 0) 489 close(fd_server); 490 _exit(exit_code); 491 } 492 self->pid_coredump_server = pid_coredump_server; 493 494 EXPECT_EQ(close(ipc_sockets[1]), 0); 495 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 496 EXPECT_EQ(close(ipc_sockets[0]), 0); 497 498 pid = fork(); 499 ASSERT_GE(pid, 0); 500 if (pid == 0) 501 crashing_child(); 502 503 pidfd = sys_pidfd_open(pid, 0); 504 ASSERT_GE(pidfd, 0); 505 506 waitpid(pid, &status, 0); 507 ASSERT_TRUE(WIFSIGNALED(status)); 508 ASSERT_FALSE(WCOREDUMP(status)); 509 510 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 511 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 512 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 513 514 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 515 } 516 517 TEST_F(coredump, socket_request_invalid_flag_combination) 518 { 519 int pidfd, ret, status; 520 pid_t pid, pid_coredump_server; 521 struct pidfd_info info = {}; 522 int ipc_sockets[2]; 523 char c; 524 525 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 526 527 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 528 ASSERT_EQ(ret, 0); 529 530 pid_coredump_server = fork(); 531 ASSERT_GE(pid_coredump_server, 0); 532 if (pid_coredump_server == 0) { 533 struct coredump_req req = {}; 534 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 535 int exit_code = EXIT_FAILURE; 536 537 close(ipc_sockets[0]); 538 539 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 540 if (fd_server < 0) { 541 fprintf(stderr, "socket_request_invalid_flag_combination: create_and_listen_unix_socket failed: %m\n"); 542 goto out; 543 } 544 545 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 546 fprintf(stderr, "socket_request_invalid_flag_combination: write_nointr to ipc socket failed: %m\n"); 547 goto out; 548 } 549 550 close(ipc_sockets[1]); 551 552 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 553 if (fd_coredump < 0) { 554 fprintf(stderr, "socket_request_invalid_flag_combination: accept4 failed: %m\n"); 555 goto out; 556 } 557 558 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 559 if (fd_peer_pidfd < 0) { 560 fprintf(stderr, "socket_request_invalid_flag_combination: get_peer_pidfd failed\n"); 561 goto out; 562 } 563 564 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 565 fprintf(stderr, "socket_request_invalid_flag_combination: get_pidfd_info failed\n"); 566 goto out; 567 } 568 569 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 570 fprintf(stderr, "socket_request_invalid_flag_combination: PIDFD_INFO_COREDUMP not set in mask\n"); 571 goto out; 572 } 573 574 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 575 fprintf(stderr, "socket_request_invalid_flag_combination: PIDFD_COREDUMPED not set in coredump_mask\n"); 576 goto out; 577 } 578 579 if (!read_coredump_req(fd_coredump, &req)) { 580 fprintf(stderr, "socket_request_invalid_flag_combination: read_coredump_req failed\n"); 581 goto out; 582 } 583 584 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 585 COREDUMP_KERNEL | COREDUMP_USERSPACE | 586 COREDUMP_REJECT | COREDUMP_WAIT)) { 587 fprintf(stderr, "socket_request_invalid_flag_combination: check_coredump_req failed\n"); 588 goto out; 589 } 590 591 if (!send_coredump_ack(fd_coredump, &req, 592 COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0)) { 593 fprintf(stderr, "socket_request_invalid_flag_combination: send_coredump_ack failed\n"); 594 goto out; 595 } 596 597 if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING)) { 598 fprintf(stderr, "socket_request_invalid_flag_combination: read_marker COREDUMP_MARK_CONFLICTING failed\n"); 599 goto out; 600 } 601 602 exit_code = EXIT_SUCCESS; 603 fprintf(stderr, "socket_request_invalid_flag_combination: completed successfully\n"); 604 out: 605 if (fd_peer_pidfd >= 0) 606 close(fd_peer_pidfd); 607 if (fd_coredump >= 0) 608 close(fd_coredump); 609 if (fd_server >= 0) 610 close(fd_server); 611 _exit(exit_code); 612 } 613 self->pid_coredump_server = pid_coredump_server; 614 615 EXPECT_EQ(close(ipc_sockets[1]), 0); 616 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 617 EXPECT_EQ(close(ipc_sockets[0]), 0); 618 619 pid = fork(); 620 ASSERT_GE(pid, 0); 621 if (pid == 0) 622 crashing_child(); 623 624 pidfd = sys_pidfd_open(pid, 0); 625 ASSERT_GE(pidfd, 0); 626 627 waitpid(pid, &status, 0); 628 ASSERT_TRUE(WIFSIGNALED(status)); 629 ASSERT_FALSE(WCOREDUMP(status)); 630 631 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 632 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 633 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 634 635 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 636 } 637 638 TEST_F(coredump, socket_request_unknown_flag) 639 { 640 int pidfd, ret, status; 641 pid_t pid, pid_coredump_server; 642 struct pidfd_info info = {}; 643 int ipc_sockets[2]; 644 char c; 645 646 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 647 648 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 649 ASSERT_EQ(ret, 0); 650 651 pid_coredump_server = fork(); 652 ASSERT_GE(pid_coredump_server, 0); 653 if (pid_coredump_server == 0) { 654 struct coredump_req req = {}; 655 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 656 int exit_code = EXIT_FAILURE; 657 658 close(ipc_sockets[0]); 659 660 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 661 if (fd_server < 0) { 662 fprintf(stderr, "socket_request_unknown_flag: create_and_listen_unix_socket failed: %m\n"); 663 goto out; 664 } 665 666 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 667 fprintf(stderr, "socket_request_unknown_flag: write_nointr to ipc socket failed: %m\n"); 668 goto out; 669 } 670 671 close(ipc_sockets[1]); 672 673 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 674 if (fd_coredump < 0) { 675 fprintf(stderr, "socket_request_unknown_flag: accept4 failed: %m\n"); 676 goto out; 677 } 678 679 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 680 if (fd_peer_pidfd < 0) { 681 fprintf(stderr, "socket_request_unknown_flag: get_peer_pidfd failed\n"); 682 goto out; 683 } 684 685 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 686 fprintf(stderr, "socket_request_unknown_flag: get_pidfd_info failed\n"); 687 goto out; 688 } 689 690 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 691 fprintf(stderr, "socket_request_unknown_flag: PIDFD_INFO_COREDUMP not set in mask\n"); 692 goto out; 693 } 694 695 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 696 fprintf(stderr, "socket_request_unknown_flag: PIDFD_COREDUMPED not set in coredump_mask\n"); 697 goto out; 698 } 699 700 if (!read_coredump_req(fd_coredump, &req)) { 701 fprintf(stderr, "socket_request_unknown_flag: read_coredump_req failed\n"); 702 goto out; 703 } 704 705 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 706 COREDUMP_KERNEL | COREDUMP_USERSPACE | 707 COREDUMP_REJECT | COREDUMP_WAIT)) { 708 fprintf(stderr, "socket_request_unknown_flag: check_coredump_req failed\n"); 709 goto out; 710 } 711 712 if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0)) { 713 fprintf(stderr, "socket_request_unknown_flag: send_coredump_ack failed\n"); 714 goto out; 715 } 716 717 if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED)) { 718 fprintf(stderr, "socket_request_unknown_flag: read_marker COREDUMP_MARK_UNSUPPORTED failed\n"); 719 goto out; 720 } 721 722 exit_code = EXIT_SUCCESS; 723 fprintf(stderr, "socket_request_unknown_flag: completed successfully\n"); 724 out: 725 if (fd_peer_pidfd >= 0) 726 close(fd_peer_pidfd); 727 if (fd_coredump >= 0) 728 close(fd_coredump); 729 if (fd_server >= 0) 730 close(fd_server); 731 _exit(exit_code); 732 } 733 self->pid_coredump_server = pid_coredump_server; 734 735 EXPECT_EQ(close(ipc_sockets[1]), 0); 736 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 737 EXPECT_EQ(close(ipc_sockets[0]), 0); 738 739 pid = fork(); 740 ASSERT_GE(pid, 0); 741 if (pid == 0) 742 crashing_child(); 743 744 pidfd = sys_pidfd_open(pid, 0); 745 ASSERT_GE(pidfd, 0); 746 747 waitpid(pid, &status, 0); 748 ASSERT_TRUE(WIFSIGNALED(status)); 749 ASSERT_FALSE(WCOREDUMP(status)); 750 751 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 752 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 753 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 754 755 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 756 } 757 758 TEST_F(coredump, socket_request_invalid_size_small) 759 { 760 int pidfd, ret, status; 761 pid_t pid, pid_coredump_server; 762 struct pidfd_info info = {}; 763 int ipc_sockets[2]; 764 char c; 765 766 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 767 768 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 769 ASSERT_EQ(ret, 0); 770 771 pid_coredump_server = fork(); 772 ASSERT_GE(pid_coredump_server, 0); 773 if (pid_coredump_server == 0) { 774 struct coredump_req req = {}; 775 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 776 int exit_code = EXIT_FAILURE; 777 778 close(ipc_sockets[0]); 779 780 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 781 if (fd_server < 0) { 782 fprintf(stderr, "socket_request_invalid_size_small: create_and_listen_unix_socket failed: %m\n"); 783 goto out; 784 } 785 786 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 787 fprintf(stderr, "socket_request_invalid_size_small: write_nointr to ipc socket failed: %m\n"); 788 goto out; 789 } 790 791 close(ipc_sockets[1]); 792 793 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 794 if (fd_coredump < 0) { 795 fprintf(stderr, "socket_request_invalid_size_small: accept4 failed: %m\n"); 796 goto out; 797 } 798 799 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 800 if (fd_peer_pidfd < 0) { 801 fprintf(stderr, "socket_request_invalid_size_small: get_peer_pidfd failed\n"); 802 goto out; 803 } 804 805 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 806 fprintf(stderr, "socket_request_invalid_size_small: get_pidfd_info failed\n"); 807 goto out; 808 } 809 810 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 811 fprintf(stderr, "socket_request_invalid_size_small: PIDFD_INFO_COREDUMP not set in mask\n"); 812 goto out; 813 } 814 815 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 816 fprintf(stderr, "socket_request_invalid_size_small: PIDFD_COREDUMPED not set in coredump_mask\n"); 817 goto out; 818 } 819 820 if (!read_coredump_req(fd_coredump, &req)) { 821 fprintf(stderr, "socket_request_invalid_size_small: read_coredump_req failed\n"); 822 goto out; 823 } 824 825 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 826 COREDUMP_KERNEL | COREDUMP_USERSPACE | 827 COREDUMP_REJECT | COREDUMP_WAIT)) { 828 fprintf(stderr, "socket_request_invalid_size_small: check_coredump_req failed\n"); 829 goto out; 830 } 831 832 if (!send_coredump_ack(fd_coredump, &req, 833 COREDUMP_REJECT | COREDUMP_WAIT, 834 COREDUMP_ACK_SIZE_VER0 / 2)) { 835 fprintf(stderr, "socket_request_invalid_size_small: send_coredump_ack failed\n"); 836 goto out; 837 } 838 839 if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE)) { 840 fprintf(stderr, "socket_request_invalid_size_small: read_marker COREDUMP_MARK_MINSIZE failed\n"); 841 goto out; 842 } 843 844 exit_code = EXIT_SUCCESS; 845 fprintf(stderr, "socket_request_invalid_size_small: completed successfully\n"); 846 out: 847 if (fd_peer_pidfd >= 0) 848 close(fd_peer_pidfd); 849 if (fd_coredump >= 0) 850 close(fd_coredump); 851 if (fd_server >= 0) 852 close(fd_server); 853 _exit(exit_code); 854 } 855 self->pid_coredump_server = pid_coredump_server; 856 857 EXPECT_EQ(close(ipc_sockets[1]), 0); 858 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 859 EXPECT_EQ(close(ipc_sockets[0]), 0); 860 861 pid = fork(); 862 ASSERT_GE(pid, 0); 863 if (pid == 0) 864 crashing_child(); 865 866 pidfd = sys_pidfd_open(pid, 0); 867 ASSERT_GE(pidfd, 0); 868 869 waitpid(pid, &status, 0); 870 ASSERT_TRUE(WIFSIGNALED(status)); 871 ASSERT_FALSE(WCOREDUMP(status)); 872 873 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 874 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 875 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 876 877 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 878 } 879 880 TEST_F(coredump, socket_request_invalid_size_large) 881 { 882 int pidfd, ret, status; 883 pid_t pid, pid_coredump_server; 884 struct pidfd_info info = {}; 885 int ipc_sockets[2]; 886 char c; 887 888 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 889 890 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 891 ASSERT_EQ(ret, 0); 892 893 pid_coredump_server = fork(); 894 ASSERT_GE(pid_coredump_server, 0); 895 if (pid_coredump_server == 0) { 896 struct coredump_req req = {}; 897 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 898 int exit_code = EXIT_FAILURE; 899 900 close(ipc_sockets[0]); 901 902 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 903 if (fd_server < 0) { 904 fprintf(stderr, "socket_request_invalid_size_large: create_and_listen_unix_socket failed: %m\n"); 905 goto out; 906 } 907 908 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 909 fprintf(stderr, "socket_request_invalid_size_large: write_nointr to ipc socket failed: %m\n"); 910 goto out; 911 } 912 913 close(ipc_sockets[1]); 914 915 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 916 if (fd_coredump < 0) { 917 fprintf(stderr, "socket_request_invalid_size_large: accept4 failed: %m\n"); 918 goto out; 919 } 920 921 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 922 if (fd_peer_pidfd < 0) { 923 fprintf(stderr, "socket_request_invalid_size_large: get_peer_pidfd failed\n"); 924 goto out; 925 } 926 927 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 928 fprintf(stderr, "socket_request_invalid_size_large: get_pidfd_info failed\n"); 929 goto out; 930 } 931 932 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 933 fprintf(stderr, "socket_request_invalid_size_large: PIDFD_INFO_COREDUMP not set in mask\n"); 934 goto out; 935 } 936 937 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 938 fprintf(stderr, "socket_request_invalid_size_large: PIDFD_COREDUMPED not set in coredump_mask\n"); 939 goto out; 940 } 941 942 if (!read_coredump_req(fd_coredump, &req)) { 943 fprintf(stderr, "socket_request_invalid_size_large: read_coredump_req failed\n"); 944 goto out; 945 } 946 947 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 948 COREDUMP_KERNEL | COREDUMP_USERSPACE | 949 COREDUMP_REJECT | COREDUMP_WAIT)) { 950 fprintf(stderr, "socket_request_invalid_size_large: check_coredump_req failed\n"); 951 goto out; 952 } 953 954 if (!send_coredump_ack(fd_coredump, &req, 955 COREDUMP_REJECT | COREDUMP_WAIT, 956 COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE)) { 957 fprintf(stderr, "socket_request_invalid_size_large: send_coredump_ack failed\n"); 958 goto out; 959 } 960 961 if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE)) { 962 fprintf(stderr, "socket_request_invalid_size_large: read_marker COREDUMP_MARK_MAXSIZE failed\n"); 963 goto out; 964 } 965 966 exit_code = EXIT_SUCCESS; 967 fprintf(stderr, "socket_request_invalid_size_large: completed successfully\n"); 968 out: 969 if (fd_peer_pidfd >= 0) 970 close(fd_peer_pidfd); 971 if (fd_coredump >= 0) 972 close(fd_coredump); 973 if (fd_server >= 0) 974 close(fd_server); 975 _exit(exit_code); 976 } 977 self->pid_coredump_server = pid_coredump_server; 978 979 EXPECT_EQ(close(ipc_sockets[1]), 0); 980 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 981 EXPECT_EQ(close(ipc_sockets[0]), 0); 982 983 pid = fork(); 984 ASSERT_GE(pid, 0); 985 if (pid == 0) 986 crashing_child(); 987 988 pidfd = sys_pidfd_open(pid, 0); 989 ASSERT_GE(pidfd, 0); 990 991 waitpid(pid, &status, 0); 992 ASSERT_TRUE(WIFSIGNALED(status)); 993 ASSERT_FALSE(WCOREDUMP(status)); 994 995 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 996 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 997 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 998 999 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 1000 } 1001 1002 /* 1003 * Test: PIDFD_INFO_COREDUMP_SIGNAL via socket coredump with SIGSEGV 1004 * 1005 * Verify that when using socket-based coredump protocol, 1006 * the coredump_signal field is correctly exposed as SIGSEGV. 1007 */ 1008 TEST_F(coredump, socket_coredump_signal_sigsegv) 1009 { 1010 int pidfd, ret, status; 1011 pid_t pid, pid_coredump_server; 1012 struct pidfd_info info = {}; 1013 int ipc_sockets[2]; 1014 char c; 1015 1016 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 1017 1018 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 1019 ASSERT_EQ(ret, 0); 1020 1021 pid_coredump_server = fork(); 1022 ASSERT_GE(pid_coredump_server, 0); 1023 if (pid_coredump_server == 0) { 1024 struct coredump_req req = {}; 1025 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 1026 int exit_code = EXIT_FAILURE; 1027 1028 close(ipc_sockets[0]); 1029 1030 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 1031 if (fd_server < 0) { 1032 fprintf(stderr, "socket_coredump_signal_sigsegv: create_and_listen_unix_socket failed: %m\n"); 1033 goto out; 1034 } 1035 1036 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 1037 fprintf(stderr, "socket_coredump_signal_sigsegv: write_nointr to ipc socket failed: %m\n"); 1038 goto out; 1039 } 1040 1041 close(ipc_sockets[1]); 1042 1043 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 1044 if (fd_coredump < 0) { 1045 fprintf(stderr, "socket_coredump_signal_sigsegv: accept4 failed: %m\n"); 1046 goto out; 1047 } 1048 1049 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 1050 if (fd_peer_pidfd < 0) { 1051 fprintf(stderr, "socket_coredump_signal_sigsegv: get_peer_pidfd failed\n"); 1052 goto out; 1053 } 1054 1055 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 1056 fprintf(stderr, "socket_coredump_signal_sigsegv: get_pidfd_info failed\n"); 1057 goto out; 1058 } 1059 1060 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 1061 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP not set in mask\n"); 1062 goto out; 1063 } 1064 1065 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 1066 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_COREDUMPED not set in coredump_mask\n"); 1067 goto out; 1068 } 1069 1070 /* Verify coredump_signal is available and correct */ 1071 if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { 1072 fprintf(stderr, "socket_coredump_signal_sigsegv: PIDFD_INFO_COREDUMP_SIGNAL not set in mask\n"); 1073 goto out; 1074 } 1075 1076 if (info.coredump_signal != SIGSEGV) { 1077 fprintf(stderr, "socket_coredump_signal_sigsegv: coredump_signal=%d, expected SIGSEGV=%d\n", 1078 info.coredump_signal, SIGSEGV); 1079 goto out; 1080 } 1081 1082 if (!read_coredump_req(fd_coredump, &req)) { 1083 fprintf(stderr, "socket_coredump_signal_sigsegv: read_coredump_req failed\n"); 1084 goto out; 1085 } 1086 1087 if (!send_coredump_ack(fd_coredump, &req, 1088 COREDUMP_REJECT | COREDUMP_WAIT, 0)) { 1089 fprintf(stderr, "socket_coredump_signal_sigsegv: send_coredump_ack failed\n"); 1090 goto out; 1091 } 1092 1093 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 1094 fprintf(stderr, "socket_coredump_signal_sigsegv: read_marker COREDUMP_MARK_REQACK failed\n"); 1095 goto out; 1096 } 1097 1098 exit_code = EXIT_SUCCESS; 1099 fprintf(stderr, "socket_coredump_signal_sigsegv: completed successfully\n"); 1100 out: 1101 if (fd_peer_pidfd >= 0) 1102 close(fd_peer_pidfd); 1103 if (fd_coredump >= 0) 1104 close(fd_coredump); 1105 if (fd_server >= 0) 1106 close(fd_server); 1107 _exit(exit_code); 1108 } 1109 self->pid_coredump_server = pid_coredump_server; 1110 1111 EXPECT_EQ(close(ipc_sockets[1]), 0); 1112 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 1113 EXPECT_EQ(close(ipc_sockets[0]), 0); 1114 1115 pid = fork(); 1116 ASSERT_GE(pid, 0); 1117 if (pid == 0) 1118 crashing_child(); 1119 1120 pidfd = sys_pidfd_open(pid, 0); 1121 ASSERT_GE(pidfd, 0); 1122 1123 waitpid(pid, &status, 0); 1124 ASSERT_TRUE(WIFSIGNALED(status)); 1125 ASSERT_EQ(WTERMSIG(status), SIGSEGV); 1126 1127 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 1128 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); 1129 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); 1130 ASSERT_EQ(info.coredump_signal, SIGSEGV); 1131 1132 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 1133 } 1134 1135 /* 1136 * Test: PIDFD_INFO_COREDUMP_SIGNAL via socket coredump with SIGABRT 1137 * 1138 * Verify that when using socket-based coredump protocol, 1139 * the coredump_signal field is correctly exposed as SIGABRT. 1140 */ 1141 TEST_F(coredump, socket_coredump_signal_sigabrt) 1142 { 1143 int pidfd, ret, status; 1144 pid_t pid, pid_coredump_server; 1145 struct pidfd_info info = {}; 1146 int ipc_sockets[2]; 1147 char c; 1148 1149 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 1150 1151 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 1152 ASSERT_EQ(ret, 0); 1153 1154 pid_coredump_server = fork(); 1155 ASSERT_GE(pid_coredump_server, 0); 1156 if (pid_coredump_server == 0) { 1157 struct coredump_req req = {}; 1158 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1; 1159 int exit_code = EXIT_FAILURE; 1160 1161 close(ipc_sockets[0]); 1162 1163 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 1164 if (fd_server < 0) { 1165 fprintf(stderr, "socket_coredump_signal_sigabrt: create_and_listen_unix_socket failed: %m\n"); 1166 goto out; 1167 } 1168 1169 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 1170 fprintf(stderr, "socket_coredump_signal_sigabrt: write_nointr to ipc socket failed: %m\n"); 1171 goto out; 1172 } 1173 1174 close(ipc_sockets[1]); 1175 1176 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 1177 if (fd_coredump < 0) { 1178 fprintf(stderr, "socket_coredump_signal_sigabrt: accept4 failed: %m\n"); 1179 goto out; 1180 } 1181 1182 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 1183 if (fd_peer_pidfd < 0) { 1184 fprintf(stderr, "socket_coredump_signal_sigabrt: get_peer_pidfd failed\n"); 1185 goto out; 1186 } 1187 1188 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 1189 fprintf(stderr, "socket_coredump_signal_sigabrt: get_pidfd_info failed\n"); 1190 goto out; 1191 } 1192 1193 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 1194 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP not set in mask\n"); 1195 goto out; 1196 } 1197 1198 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 1199 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_COREDUMPED not set in coredump_mask\n"); 1200 goto out; 1201 } 1202 1203 /* Verify coredump_signal is available and correct */ 1204 if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) { 1205 fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_SIGNAL not set in mask\n"); 1206 goto out; 1207 } 1208 1209 if (info.coredump_signal != SIGABRT) { 1210 fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_signal=%d, expected SIGABRT=%d\n", 1211 info.coredump_signal, SIGABRT); 1212 goto out; 1213 } 1214 1215 if (!read_coredump_req(fd_coredump, &req)) { 1216 fprintf(stderr, "socket_coredump_signal_sigabrt: read_coredump_req failed\n"); 1217 goto out; 1218 } 1219 1220 if (!send_coredump_ack(fd_coredump, &req, 1221 COREDUMP_REJECT | COREDUMP_WAIT, 0)) { 1222 fprintf(stderr, "socket_coredump_signal_sigabrt: send_coredump_ack failed\n"); 1223 goto out; 1224 } 1225 1226 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 1227 fprintf(stderr, "socket_coredump_signal_sigabrt: read_marker COREDUMP_MARK_REQACK failed\n"); 1228 goto out; 1229 } 1230 1231 exit_code = EXIT_SUCCESS; 1232 fprintf(stderr, "socket_coredump_signal_sigabrt: completed successfully\n"); 1233 out: 1234 if (fd_peer_pidfd >= 0) 1235 close(fd_peer_pidfd); 1236 if (fd_coredump >= 0) 1237 close(fd_coredump); 1238 if (fd_server >= 0) 1239 close(fd_server); 1240 _exit(exit_code); 1241 } 1242 self->pid_coredump_server = pid_coredump_server; 1243 1244 EXPECT_EQ(close(ipc_sockets[1]), 0); 1245 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 1246 EXPECT_EQ(close(ipc_sockets[0]), 0); 1247 1248 pid = fork(); 1249 ASSERT_GE(pid, 0); 1250 if (pid == 0) 1251 abort(); 1252 1253 pidfd = sys_pidfd_open(pid, 0); 1254 ASSERT_GE(pidfd, 0); 1255 1256 waitpid(pid, &status, 0); 1257 ASSERT_TRUE(WIFSIGNALED(status)); 1258 ASSERT_EQ(WTERMSIG(status), SIGABRT); 1259 1260 ASSERT_TRUE(get_pidfd_info(pidfd, &info)); 1261 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP)); 1262 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)); 1263 ASSERT_EQ(info.coredump_signal, SIGABRT); 1264 1265 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 1266 } 1267 1268 TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps, 500) 1269 { 1270 int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; 1271 pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server; 1272 struct pidfd_info info = {}; 1273 int ipc_sockets[2]; 1274 char c; 1275 1276 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 1277 1278 ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets), 0); 1279 1280 pid_coredump_server = fork(); 1281 ASSERT_GE(pid_coredump_server, 0); 1282 if (pid_coredump_server == 0) { 1283 int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1; 1284 int exit_code = EXIT_FAILURE; 1285 struct coredump_req req = {}; 1286 1287 close(ipc_sockets[0]); 1288 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 1289 if (fd_server < 0) { 1290 fprintf(stderr, "Failed to create and listen on unix socket\n"); 1291 goto out; 1292 } 1293 1294 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 1295 fprintf(stderr, "Failed to notify parent via ipc socket\n"); 1296 goto out; 1297 } 1298 close(ipc_sockets[1]); 1299 1300 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1301 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 1302 if (fd_coredump < 0) { 1303 fprintf(stderr, "accept4 failed: %m\n"); 1304 goto out; 1305 } 1306 1307 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 1308 if (fd_peer_pidfd < 0) { 1309 fprintf(stderr, "get_peer_pidfd failed for fd %d: %m\n", fd_coredump); 1310 goto out; 1311 } 1312 1313 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 1314 fprintf(stderr, "get_pidfd_info failed for fd %d\n", fd_peer_pidfd); 1315 goto out; 1316 } 1317 1318 if (!(info.mask & PIDFD_INFO_COREDUMP)) { 1319 fprintf(stderr, "pidfd info missing PIDFD_INFO_COREDUMP for fd %d\n", fd_peer_pidfd); 1320 goto out; 1321 } 1322 if (!(info.coredump_mask & PIDFD_COREDUMPED)) { 1323 fprintf(stderr, "pidfd info missing PIDFD_COREDUMPED for fd %d\n", fd_peer_pidfd); 1324 goto out; 1325 } 1326 1327 if (!read_coredump_req(fd_coredump, &req)) { 1328 fprintf(stderr, "read_coredump_req failed for fd %d\n", fd_coredump); 1329 goto out; 1330 } 1331 1332 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 1333 COREDUMP_KERNEL | COREDUMP_USERSPACE | 1334 COREDUMP_REJECT | COREDUMP_WAIT)) { 1335 fprintf(stderr, "check_coredump_req failed for fd %d\n", fd_coredump); 1336 goto out; 1337 } 1338 1339 if (!send_coredump_ack(fd_coredump, &req, 1340 COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { 1341 fprintf(stderr, "send_coredump_ack failed for fd %d\n", fd_coredump); 1342 goto out; 1343 } 1344 1345 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 1346 fprintf(stderr, "read_marker failed for fd %d\n", fd_coredump); 1347 goto out; 1348 } 1349 1350 fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached); 1351 if (fd_core_file < 0) { 1352 fprintf(stderr, "%m - open_coredump_tmpfile failed for fd %d\n", fd_coredump); 1353 goto out; 1354 } 1355 1356 for (;;) { 1357 char buffer[4096]; 1358 ssize_t bytes_read, bytes_write; 1359 1360 bytes_read = read(fd_coredump, buffer, sizeof(buffer)); 1361 if (bytes_read < 0) { 1362 fprintf(stderr, "read failed for fd %d: %m\n", fd_coredump); 1363 goto out; 1364 } 1365 1366 if (bytes_read == 0) 1367 break; 1368 1369 bytes_write = write(fd_core_file, buffer, bytes_read); 1370 if (bytes_read != bytes_write) { 1371 if (bytes_write < 0 && errno == ENOSPC) 1372 continue; 1373 fprintf(stderr, "write failed for fd %d: %m\n", fd_core_file); 1374 goto out; 1375 } 1376 } 1377 1378 close(fd_core_file); 1379 close(fd_peer_pidfd); 1380 close(fd_coredump); 1381 fd_peer_pidfd = -1; 1382 fd_coredump = -1; 1383 } 1384 1385 exit_code = EXIT_SUCCESS; 1386 out: 1387 if (fd_core_file >= 0) 1388 close(fd_core_file); 1389 if (fd_peer_pidfd >= 0) 1390 close(fd_peer_pidfd); 1391 if (fd_coredump >= 0) 1392 close(fd_coredump); 1393 if (fd_server >= 0) 1394 close(fd_server); 1395 _exit(exit_code); 1396 } 1397 self->pid_coredump_server = pid_coredump_server; 1398 1399 EXPECT_EQ(close(ipc_sockets[1]), 0); 1400 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 1401 EXPECT_EQ(close(ipc_sockets[0]), 0); 1402 1403 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1404 pid[i] = fork(); 1405 ASSERT_GE(pid[i], 0); 1406 if (pid[i] == 0) 1407 crashing_child(); 1408 pidfd[i] = sys_pidfd_open(pid[i], 0); 1409 ASSERT_GE(pidfd[i], 0); 1410 } 1411 1412 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1413 waitpid(pid[i], &status[i], 0); 1414 ASSERT_TRUE(WIFSIGNALED(status[i])); 1415 ASSERT_TRUE(WCOREDUMP(status[i])); 1416 } 1417 1418 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1419 info.mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; 1420 ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); 1421 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 1422 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 1423 } 1424 1425 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 1426 } 1427 1428 TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps_epoll_workers, 500) 1429 { 1430 int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS]; 1431 pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server, worker_pids[NUM_CRASHING_COREDUMPS]; 1432 struct pidfd_info info = {}; 1433 int ipc_sockets[2]; 1434 char c; 1435 1436 ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket")); 1437 ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets), 0); 1438 1439 pid_coredump_server = fork(); 1440 ASSERT_GE(pid_coredump_server, 0); 1441 if (pid_coredump_server == 0) { 1442 int fd_server = -1, exit_code = EXIT_FAILURE, n_conns = 0; 1443 fd_server = -1; 1444 exit_code = EXIT_FAILURE; 1445 n_conns = 0; 1446 close(ipc_sockets[0]); 1447 fd_server = create_and_listen_unix_socket("/tmp/coredump.socket"); 1448 if (fd_server < 0) { 1449 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: create_and_listen_unix_socket failed: %m\n"); 1450 goto out; 1451 } 1452 1453 if (write_nointr(ipc_sockets[1], "1", 1) < 0) { 1454 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: write_nointr to ipc socket failed: %m\n"); 1455 goto out; 1456 } 1457 close(ipc_sockets[1]); 1458 1459 while (n_conns < NUM_CRASHING_COREDUMPS) { 1460 int fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1; 1461 struct coredump_req req = {}; 1462 fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC); 1463 if (fd_coredump < 0) { 1464 if (errno == EAGAIN || errno == EWOULDBLOCK) 1465 continue; 1466 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: accept4 failed: %m\n"); 1467 goto out; 1468 } 1469 fd_peer_pidfd = get_peer_pidfd(fd_coredump); 1470 if (fd_peer_pidfd < 0) { 1471 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: get_peer_pidfd failed\n"); 1472 goto out; 1473 } 1474 if (!get_pidfd_info(fd_peer_pidfd, &info)) { 1475 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: get_pidfd_info failed\n"); 1476 goto out; 1477 } 1478 if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_COREDUMPED)) { 1479 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: missing PIDFD_INFO_COREDUMP or PIDFD_COREDUMPED\n"); 1480 goto out; 1481 } 1482 if (!read_coredump_req(fd_coredump, &req)) { 1483 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: read_coredump_req failed\n"); 1484 goto out; 1485 } 1486 if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0, 1487 COREDUMP_KERNEL | COREDUMP_USERSPACE | 1488 COREDUMP_REJECT | COREDUMP_WAIT)) { 1489 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: check_coredump_req failed\n"); 1490 goto out; 1491 } 1492 if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WAIT, 0)) { 1493 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: send_coredump_ack failed\n"); 1494 goto out; 1495 } 1496 if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) { 1497 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: read_marker failed\n"); 1498 goto out; 1499 } 1500 fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached); 1501 if (fd_core_file < 0) { 1502 fprintf(stderr, "socket_multiple_crashing_coredumps_epoll_workers: open_coredump_tmpfile failed: %m\n"); 1503 goto out; 1504 } 1505 pid_t worker = fork(); 1506 if (worker == 0) { 1507 close(fd_server); 1508 process_coredump_worker(fd_coredump, fd_peer_pidfd, fd_core_file); 1509 } 1510 worker_pids[n_conns] = worker; 1511 if (fd_coredump >= 0) 1512 close(fd_coredump); 1513 if (fd_peer_pidfd >= 0) 1514 close(fd_peer_pidfd); 1515 if (fd_core_file >= 0) 1516 close(fd_core_file); 1517 n_conns++; 1518 } 1519 exit_code = EXIT_SUCCESS; 1520 out: 1521 if (fd_server >= 0) 1522 close(fd_server); 1523 1524 // Reap all worker processes 1525 for (int i = 0; i < n_conns; i++) { 1526 int wstatus; 1527 if (waitpid(worker_pids[i], &wstatus, 0) < 0) { 1528 fprintf(stderr, "Failed to wait for worker %d: %m\n", worker_pids[i]); 1529 } else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != EXIT_SUCCESS) { 1530 fprintf(stderr, "Worker %d exited with error code %d\n", worker_pids[i], WEXITSTATUS(wstatus)); 1531 exit_code = EXIT_FAILURE; 1532 } 1533 } 1534 1535 _exit(exit_code); 1536 } 1537 self->pid_coredump_server = pid_coredump_server; 1538 1539 EXPECT_EQ(close(ipc_sockets[1]), 0); 1540 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 1541 EXPECT_EQ(close(ipc_sockets[0]), 0); 1542 1543 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1544 pid[i] = fork(); 1545 ASSERT_GE(pid[i], 0); 1546 if (pid[i] == 0) 1547 crashing_child(); 1548 pidfd[i] = sys_pidfd_open(pid[i], 0); 1549 ASSERT_GE(pidfd[i], 0); 1550 } 1551 1552 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1553 ASSERT_GE(waitpid(pid[i], &status[i], 0), 0); 1554 ASSERT_TRUE(WIFSIGNALED(status[i])); 1555 ASSERT_TRUE(WCOREDUMP(status[i])); 1556 } 1557 1558 for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) { 1559 info.mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP; 1560 ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0); 1561 ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0); 1562 ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0); 1563 } 1564 1565 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 1566 } 1567 1568 TEST_HARNESS_MAIN 1569