selftests/clone3: Avoid OS-defined clone_args
[linux-2.6-microblaze.git] / tools / testing / selftests / clone3 / clone3_clear_sighand.c
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 }