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