Skip to content

Commit 619e222

Browse files
committed
selftests/coredump: add first PIDFD_INFO_COREDUMP_SIGNAL test
Verify that when using simple socket-based coredump (@ pattern), the coredump_signal field is correctly exposed as SIGSEGV. Link: https://patch.msgid.link/20251028-work-coredump-signal-v1-21-ca449b7b7aa0@kernel.org Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 32ae33f commit 619e222

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

tools/testing/selftests/coredump/coredump_socket_test.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,152 @@ TEST_F(coredump, socket_no_listener)
430430
wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
431431
}
432432

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+
*/
439+
TEST_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");
541+
out:
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+
433579
TEST_F(coredump, socket_invalid_paths)
434580
{
435581
ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket"));

0 commit comments

Comments
 (0)