xref: /linux/tools/testing/selftests/clone3/clone3_clear_sighand.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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