1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #define _GNU_SOURCE 4 #include <errno.h> 5 #include <sched.h> 6 #include <signal.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <linux/sched.h> 12 #include <linux/types.h> 13 #include <sys/syscall.h> 14 #include <sys/wait.h> 15 16 #include "../kselftest.h" 17 #include "clone3_selftests.h" 18 19 static void nop_handler(int signo) 20 { 21 } 22 23 static int wait_for_pid(pid_t pid) 24 { 25 int status, ret; 26 27 again: 28 ret = waitpid(pid, &status, 0); 29 if (ret == -1) { 30 if (errno == EINTR) 31 goto again; 32 33 return -1; 34 } 35 36 if (!WIFEXITED(status)) 37 return -1; 38 39 return WEXITSTATUS(status); 40 } 41 42 static void test_clone3_clear_sighand(void) 43 { 44 int ret; 45 pid_t pid; 46 struct __clone_args args = {}; 47 struct sigaction act; 48 49 /* 50 * Check that CLONE_CLEAR_SIGHAND and CLONE_SIGHAND are mutually 51 * exclusive. 52 */ 53 args.flags |= CLONE_CLEAR_SIGHAND | CLONE_SIGHAND; 54 args.exit_signal = SIGCHLD; 55 pid = sys_clone3(&args, sizeof(args)); 56 if (pid > 0) 57 ksft_exit_fail_msg( 58 "clone3(CLONE_CLEAR_SIGHAND | CLONE_SIGHAND) succeeded\n"); 59 60 act.sa_handler = nop_handler; 61 ret = sigemptyset(&act.sa_mask); 62 if (ret < 0) 63 ksft_exit_fail_msg("%s - sigemptyset() failed\n", 64 strerror(errno)); 65 66 act.sa_flags = 0; 67 68 /* Register signal handler for SIGUSR1 */ 69 ret = sigaction(SIGUSR1, &act, NULL); 70 if (ret < 0) 71 ksft_exit_fail_msg( 72 "%s - sigaction(SIGUSR1, &act, NULL) failed\n", 73 strerror(errno)); 74 75 /* Register signal handler for SIGUSR2 */ 76 ret = sigaction(SIGUSR2, &act, NULL); 77 if (ret < 0) 78 ksft_exit_fail_msg( 79 "%s - sigaction(SIGUSR2, &act, NULL) failed\n", 80 strerror(errno)); 81 82 /* Check that CLONE_CLEAR_SIGHAND works. */ 83 args.flags = CLONE_CLEAR_SIGHAND; 84 pid = sys_clone3(&args, sizeof(args)); 85 if (pid < 0) 86 ksft_exit_fail_msg("%s - clone3(CLONE_CLEAR_SIGHAND) failed\n", 87 strerror(errno)); 88 89 if (pid == 0) { 90 ret = sigaction(SIGUSR1, NULL, &act); 91 if (ret < 0) 92 exit(EXIT_FAILURE); 93 94 if (act.sa_handler != SIG_DFL) 95 exit(EXIT_FAILURE); 96 97 ret = sigaction(SIGUSR2, NULL, &act); 98 if (ret < 0) 99 exit(EXIT_FAILURE); 100 101 if (act.sa_handler != SIG_DFL) 102 exit(EXIT_FAILURE); 103 104 exit(EXIT_SUCCESS); 105 } 106 107 ret = wait_for_pid(pid); 108 if (ret) 109 ksft_exit_fail_msg( 110 "Failed to clear signal handler for child process\n"); 111 112 ksft_test_result_pass("Cleared signal handlers for child process\n"); 113 } 114 115 int main(int argc, char **argv) 116 { 117 ksft_print_header(); 118 ksft_set_plan(1); 119 test_clone3_supported(); 120 121 test_clone3_clear_sighand(); 122 123 ksft_exit_pass(); 124 } 125