2019-10-14 12:45:38 +02:00
/* SPDX-License-Identifier: GPL-2.0 */
# define _GNU_SOURCE
# include <errno.h>
# include <sched.h>
# include <signal.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <linux/sched.h>
# include <linux/types.h>
# include <sys/syscall.h>
# include <sys/wait.h>
# include "../kselftest.h"
2019-11-15 13:36:21 +01:00
# include "clone3_selftests.h"
2019-10-14 12:45:38 +02:00
# ifndef CLONE_CLEAR_SIGHAND
# define CLONE_CLEAR_SIGHAND 0x100000000ULL
# endif
static void nop_handler ( int signo )
{
}
static int wait_for_pid ( pid_t pid )
{
int status , ret ;
again :
ret = waitpid ( pid , & status , 0 ) ;
if ( ret = = - 1 ) {
if ( errno = = EINTR )
goto again ;
return - 1 ;
}
if ( ! WIFEXITED ( status ) )
return - 1 ;
return WEXITSTATUS ( status ) ;
}
static void test_clone3_clear_sighand ( void )
{
int ret ;
pid_t pid ;
2020-09-12 04:08:19 -07:00
struct __clone_args args = { } ;
2019-10-14 12:45:38 +02:00
struct sigaction act ;
/*
* Check that CLONE_CLEAR_SIGHAND and CLONE_SIGHAND are mutually
* exclusive .
*/
args . flags | = CLONE_CLEAR_SIGHAND | CLONE_SIGHAND ;
args . exit_signal = SIGCHLD ;
pid = sys_clone3 ( & args , sizeof ( args ) ) ;
if ( pid > 0 )
ksft_exit_fail_msg (
" clone3(CLONE_CLEAR_SIGHAND | CLONE_SIGHAND) succeeded \n " ) ;
act . sa_handler = nop_handler ;
ret = sigemptyset ( & act . sa_mask ) ;
if ( ret < 0 )
ksft_exit_fail_msg ( " %s - sigemptyset() failed \n " ,
strerror ( errno ) ) ;
act . sa_flags = 0 ;
/* Register signal handler for SIGUSR1 */
ret = sigaction ( SIGUSR1 , & act , NULL ) ;
if ( ret < 0 )
ksft_exit_fail_msg (
" %s - sigaction(SIGUSR1, &act, NULL) failed \n " ,
strerror ( errno ) ) ;
/* Register signal handler for SIGUSR2 */
ret = sigaction ( SIGUSR2 , & act , NULL ) ;
if ( ret < 0 )
ksft_exit_fail_msg (
" %s - sigaction(SIGUSR2, &act, NULL) failed \n " ,
strerror ( errno ) ) ;
/* Check that CLONE_CLEAR_SIGHAND works. */
args . flags = CLONE_CLEAR_SIGHAND ;
pid = sys_clone3 ( & args , sizeof ( args ) ) ;
if ( pid < 0 )
ksft_exit_fail_msg ( " %s - clone3(CLONE_CLEAR_SIGHAND) failed \n " ,
strerror ( errno ) ) ;
if ( pid = = 0 ) {
ret = sigaction ( SIGUSR1 , NULL , & act ) ;
if ( ret < 0 )
exit ( EXIT_FAILURE ) ;
if ( act . sa_handler ! = SIG_DFL )
exit ( EXIT_FAILURE ) ;
ret = sigaction ( SIGUSR2 , NULL , & act ) ;
if ( ret < 0 )
exit ( EXIT_FAILURE ) ;
if ( act . sa_handler ! = SIG_DFL )
exit ( EXIT_FAILURE ) ;
exit ( EXIT_SUCCESS ) ;
}
ret = wait_for_pid ( pid ) ;
if ( ret )
ksft_exit_fail_msg (
" Failed to clear signal handler for child process \n " ) ;
ksft_test_result_pass ( " Cleared signal handlers for child process \n " ) ;
}
int main ( int argc , char * * argv )
{
ksft_print_header ( ) ;
ksft_set_plan ( 1 ) ;
2020-06-22 11:16:44 -07:00
test_clone3_supported ( ) ;
2019-10-14 12:45:38 +02:00
test_clone3_clear_sighand ( ) ;
return ksft_exit_pass ( ) ;
}