18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#define _GNU_SOURCE
48c2ecf20Sopenharmony_ci#include <errno.h>
58c2ecf20Sopenharmony_ci#include <sched.h>
68c2ecf20Sopenharmony_ci#include <signal.h>
78c2ecf20Sopenharmony_ci#include <stdio.h>
88c2ecf20Sopenharmony_ci#include <stdlib.h>
98c2ecf20Sopenharmony_ci#include <string.h>
108c2ecf20Sopenharmony_ci#include <unistd.h>
118c2ecf20Sopenharmony_ci#include <linux/sched.h>
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci#include <sys/syscall.h>
148c2ecf20Sopenharmony_ci#include <sys/wait.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "../kselftest.h"
178c2ecf20Sopenharmony_ci#include "clone3_selftests.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#ifndef CLONE_CLEAR_SIGHAND
208c2ecf20Sopenharmony_ci#define CLONE_CLEAR_SIGHAND 0x100000000ULL
218c2ecf20Sopenharmony_ci#endif
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic void nop_handler(int signo)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int wait_for_pid(pid_t pid)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	int status, ret;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciagain:
328c2ecf20Sopenharmony_ci	ret = waitpid(pid, &status, 0);
338c2ecf20Sopenharmony_ci	if (ret == -1) {
348c2ecf20Sopenharmony_ci		if (errno == EINTR)
358c2ecf20Sopenharmony_ci			goto again;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci		return -1;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (!WIFEXITED(status))
418c2ecf20Sopenharmony_ci		return -1;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	return WEXITSTATUS(status);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic void test_clone3_clear_sighand(void)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	int ret;
498c2ecf20Sopenharmony_ci	pid_t pid;
508c2ecf20Sopenharmony_ci	struct __clone_args args = {};
518c2ecf20Sopenharmony_ci	struct sigaction act;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/*
548c2ecf20Sopenharmony_ci	 * Check that CLONE_CLEAR_SIGHAND and CLONE_SIGHAND are mutually
558c2ecf20Sopenharmony_ci	 * exclusive.
568c2ecf20Sopenharmony_ci	 */
578c2ecf20Sopenharmony_ci	args.flags |= CLONE_CLEAR_SIGHAND | CLONE_SIGHAND;
588c2ecf20Sopenharmony_ci	args.exit_signal = SIGCHLD;
598c2ecf20Sopenharmony_ci	pid = sys_clone3(&args, sizeof(args));
608c2ecf20Sopenharmony_ci	if (pid > 0)
618c2ecf20Sopenharmony_ci		ksft_exit_fail_msg(
628c2ecf20Sopenharmony_ci			"clone3(CLONE_CLEAR_SIGHAND | CLONE_SIGHAND) succeeded\n");
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	act.sa_handler = nop_handler;
658c2ecf20Sopenharmony_ci	ret = sigemptyset(&act.sa_mask);
668c2ecf20Sopenharmony_ci	if (ret < 0)
678c2ecf20Sopenharmony_ci		ksft_exit_fail_msg("%s - sigemptyset() failed\n",
688c2ecf20Sopenharmony_ci				   strerror(errno));
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	act.sa_flags = 0;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* Register signal handler for SIGUSR1 */
738c2ecf20Sopenharmony_ci	ret = sigaction(SIGUSR1, &act, NULL);
748c2ecf20Sopenharmony_ci	if (ret < 0)
758c2ecf20Sopenharmony_ci		ksft_exit_fail_msg(
768c2ecf20Sopenharmony_ci			"%s - sigaction(SIGUSR1, &act, NULL) failed\n",
778c2ecf20Sopenharmony_ci			strerror(errno));
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/* Register signal handler for SIGUSR2 */
808c2ecf20Sopenharmony_ci	ret = sigaction(SIGUSR2, &act, NULL);
818c2ecf20Sopenharmony_ci	if (ret < 0)
828c2ecf20Sopenharmony_ci		ksft_exit_fail_msg(
838c2ecf20Sopenharmony_ci			"%s - sigaction(SIGUSR2, &act, NULL) failed\n",
848c2ecf20Sopenharmony_ci			strerror(errno));
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* Check that CLONE_CLEAR_SIGHAND works. */
878c2ecf20Sopenharmony_ci	args.flags = CLONE_CLEAR_SIGHAND;
888c2ecf20Sopenharmony_ci	pid = sys_clone3(&args, sizeof(args));
898c2ecf20Sopenharmony_ci	if (pid < 0)
908c2ecf20Sopenharmony_ci		ksft_exit_fail_msg("%s - clone3(CLONE_CLEAR_SIGHAND) failed\n",
918c2ecf20Sopenharmony_ci				   strerror(errno));
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (pid == 0) {
948c2ecf20Sopenharmony_ci		ret = sigaction(SIGUSR1, NULL, &act);
958c2ecf20Sopenharmony_ci		if (ret < 0)
968c2ecf20Sopenharmony_ci			exit(EXIT_FAILURE);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		if (act.sa_handler != SIG_DFL)
998c2ecf20Sopenharmony_ci			exit(EXIT_FAILURE);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci		ret = sigaction(SIGUSR2, NULL, &act);
1028c2ecf20Sopenharmony_ci		if (ret < 0)
1038c2ecf20Sopenharmony_ci			exit(EXIT_FAILURE);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci		if (act.sa_handler != SIG_DFL)
1068c2ecf20Sopenharmony_ci			exit(EXIT_FAILURE);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci		exit(EXIT_SUCCESS);
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	ret = wait_for_pid(pid);
1128c2ecf20Sopenharmony_ci	if (ret)
1138c2ecf20Sopenharmony_ci		ksft_exit_fail_msg(
1148c2ecf20Sopenharmony_ci			"Failed to clear signal handler for child process\n");
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	ksft_test_result_pass("Cleared signal handlers for child process\n");
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ciint main(int argc, char **argv)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	ksft_print_header();
1228c2ecf20Sopenharmony_ci	ksft_set_plan(1);
1238c2ecf20Sopenharmony_ci	test_clone3_supported();
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	test_clone3_clear_sighand();
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return ksft_exit_pass();
1288c2ecf20Sopenharmony_ci}
129