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