@@ -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+
433579TEST_F (coredump , socket_invalid_paths )
434580{
435581 ASSERT_FALSE (set_core_pattern ("@ /tmp/coredump.socket" ));
0 commit comments