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
19static void nop_handler(int signo)
20{
21}
22
23static int wait_for_pid(pid_t pid)
24{
25 int status, ret;
26
27again:
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
42static 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: &args, size: sizeof(args));
56 if (pid > 0)
57 ksft_exit_fail_msg(
58 msg: "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(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 msg: "%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 msg: "%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: &args, size: sizeof(args));
85 if (pid < 0)
86 ksft_exit_fail_msg(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 msg: "Failed to clear signal handler for child process\n");
111
112 ksft_test_result_pass(msg: "Cleared signal handlers for child process\n");
113}
114
115int main(int argc, char **argv)
116{
117 ksft_print_header();
118 ksft_set_plan(plan: 1);
119 test_clone3_supported();
120
121 test_clone3_clear_sighand();
122
123 return ksft_exit_pass();
124}
125

source code of linux/tools/testing/selftests/clone3/clone3_clear_sighand.c