mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
619e2227cc
commit
cbb842548a
|
|
@ -576,6 +576,152 @@ TEST_F(coredump, socket_coredump_signal_sigsegv)
|
|||
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: PIDFD_INFO_COREDUMP_SIGNAL via simple socket coredump with SIGABRT
|
||||
*
|
||||
* Verify that when using simple socket-based coredump (@ pattern),
|
||||
* the coredump_signal field is correctly exposed as SIGABRT.
|
||||
*/
|
||||
TEST_F(coredump, socket_coredump_signal_sigabrt)
|
||||
{
|
||||
int pidfd, ret, status;
|
||||
pid_t pid, pid_coredump_server;
|
||||
struct pidfd_info info = {};
|
||||
int ipc_sockets[2];
|
||||
char c;
|
||||
|
||||
ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket"));
|
||||
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
|
||||
ASSERT_EQ(ret, 0);
|
||||
|
||||
pid_coredump_server = fork();
|
||||
ASSERT_GE(pid_coredump_server, 0);
|
||||
if (pid_coredump_server == 0) {
|
||||
int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1;
|
||||
int exit_code = EXIT_FAILURE;
|
||||
|
||||
close(ipc_sockets[0]);
|
||||
|
||||
fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
|
||||
if (fd_server < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: create_and_listen_unix_socket failed: %m\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write_nointr(ipc_sockets[1], "1", 1) < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: write_nointr to ipc socket failed: %m\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
close(ipc_sockets[1]);
|
||||
|
||||
fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
|
||||
if (fd_coredump < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: accept4 failed: %m\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_peer_pidfd = get_peer_pidfd(fd_coredump);
|
||||
if (fd_peer_pidfd < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: get_peer_pidfd failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!get_pidfd_info(fd_peer_pidfd, &info)) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: get_pidfd_info failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(info.mask & PIDFD_INFO_COREDUMP)) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP not set in mask\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(info.coredump_mask & PIDFD_COREDUMPED)) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_COREDUMPED not set in coredump_mask\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Verify coredump_signal is available and correct */
|
||||
if (!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL)) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: PIDFD_INFO_COREDUMP_SIGNAL not set in mask\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info.coredump_signal != SIGABRT) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: coredump_signal=%d, expected SIGABRT=%d\n",
|
||||
info.coredump_signal, SIGABRT);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached);
|
||||
if (fd_core_file < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: open_coredump_tmpfile failed: %m\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
char buffer[4096];
|
||||
ssize_t bytes_read, bytes_write;
|
||||
|
||||
bytes_read = read(fd_coredump, buffer, sizeof(buffer));
|
||||
if (bytes_read < 0) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: read from coredump socket failed: %m\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
|
||||
bytes_write = write(fd_core_file, buffer, bytes_read);
|
||||
if (bytes_read != bytes_write) {
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: write to core file failed (read=%zd, write=%zd): %m\n",
|
||||
bytes_read, bytes_write);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
exit_code = EXIT_SUCCESS;
|
||||
fprintf(stderr, "socket_coredump_signal_sigabrt: completed successfully\n");
|
||||
out:
|
||||
if (fd_core_file >= 0)
|
||||
close(fd_core_file);
|
||||
if (fd_peer_pidfd >= 0)
|
||||
close(fd_peer_pidfd);
|
||||
if (fd_coredump >= 0)
|
||||
close(fd_coredump);
|
||||
if (fd_server >= 0)
|
||||
close(fd_server);
|
||||
_exit(exit_code);
|
||||
}
|
||||
self->pid_coredump_server = pid_coredump_server;
|
||||
|
||||
EXPECT_EQ(close(ipc_sockets[1]), 0);
|
||||
ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
|
||||
EXPECT_EQ(close(ipc_sockets[0]), 0);
|
||||
|
||||
pid = fork();
|
||||
ASSERT_GE(pid, 0);
|
||||
if (pid == 0)
|
||||
abort();
|
||||
|
||||
pidfd = sys_pidfd_open(pid, 0);
|
||||
ASSERT_GE(pidfd, 0);
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
ASSERT_TRUE(WIFSIGNALED(status));
|
||||
ASSERT_EQ(WTERMSIG(status), SIGABRT);
|
||||
ASSERT_TRUE(WCOREDUMP(status));
|
||||
|
||||
ASSERT_TRUE(get_pidfd_info(pidfd, &info));
|
||||
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP));
|
||||
ASSERT_TRUE(!!(info.mask & PIDFD_INFO_COREDUMP_SIGNAL));
|
||||
ASSERT_EQ(info.coredump_signal, SIGABRT);
|
||||
|
||||
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
|
||||
}
|
||||
|
||||
TEST_F(coredump, socket_invalid_paths)
|
||||
{
|
||||
ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue