Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/coredump: add second PIDFD_INFO_COREDUMP_SIGNAL test

Verify that when using simple socket-based coredump (@ pattern),
the coredump_signal field is correctly exposed as SIGABRT.

Link: https://patch.msgid.link/20251028-work-coredump-signal-v1-22-ca449b7b7aa0@kernel.org
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+146
+146
tools/testing/selftests/coredump/coredump_socket_test.c
··· 576 576 wait_and_check_coredump_server(pid_coredump_server, _metadata, self); 577 577 } 578 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 + */ 585 + TEST_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"); 687 + out: 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 + 579 725 TEST_F(coredump, socket_invalid_paths) 580 726 { 581 727 ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket"));