162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#define _GNU_SOURCE 462306a36Sopenharmony_ci#include <errno.h> 562306a36Sopenharmony_ci#include <sched.h> 662306a36Sopenharmony_ci#include <signal.h> 762306a36Sopenharmony_ci#include <stdio.h> 862306a36Sopenharmony_ci#include <stdlib.h> 962306a36Sopenharmony_ci#include <string.h> 1062306a36Sopenharmony_ci#include <unistd.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <sys/syscall.h> 1462306a36Sopenharmony_ci#include <sys/wait.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "../kselftest.h" 1762306a36Sopenharmony_ci#include "clone3_selftests.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#ifndef CLONE_CLEAR_SIGHAND 2062306a36Sopenharmony_ci#define CLONE_CLEAR_SIGHAND 0x100000000ULL 2162306a36Sopenharmony_ci#endif 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void nop_handler(int signo) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int wait_for_pid(pid_t pid) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci int status, ret; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciagain: 3262306a36Sopenharmony_ci ret = waitpid(pid, &status, 0); 3362306a36Sopenharmony_ci if (ret == -1) { 3462306a36Sopenharmony_ci if (errno == EINTR) 3562306a36Sopenharmony_ci goto again; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return -1; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (!WIFEXITED(status)) 4162306a36Sopenharmony_ci return -1; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return WEXITSTATUS(status); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic void test_clone3_clear_sighand(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci int ret; 4962306a36Sopenharmony_ci pid_t pid; 5062306a36Sopenharmony_ci struct __clone_args args = {}; 5162306a36Sopenharmony_ci struct sigaction act; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* 5462306a36Sopenharmony_ci * Check that CLONE_CLEAR_SIGHAND and CLONE_SIGHAND are mutually 5562306a36Sopenharmony_ci * exclusive. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci args.flags |= CLONE_CLEAR_SIGHAND | CLONE_SIGHAND; 5862306a36Sopenharmony_ci args.exit_signal = SIGCHLD; 5962306a36Sopenharmony_ci pid = sys_clone3(&args, sizeof(args)); 6062306a36Sopenharmony_ci if (pid > 0) 6162306a36Sopenharmony_ci ksft_exit_fail_msg( 6262306a36Sopenharmony_ci "clone3(CLONE_CLEAR_SIGHAND | CLONE_SIGHAND) succeeded\n"); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci act.sa_handler = nop_handler; 6562306a36Sopenharmony_ci ret = sigemptyset(&act.sa_mask); 6662306a36Sopenharmony_ci if (ret < 0) 6762306a36Sopenharmony_ci ksft_exit_fail_msg("%s - sigemptyset() failed\n", 6862306a36Sopenharmony_ci strerror(errno)); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci act.sa_flags = 0; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* Register signal handler for SIGUSR1 */ 7362306a36Sopenharmony_ci ret = sigaction(SIGUSR1, &act, NULL); 7462306a36Sopenharmony_ci if (ret < 0) 7562306a36Sopenharmony_ci ksft_exit_fail_msg( 7662306a36Sopenharmony_ci "%s - sigaction(SIGUSR1, &act, NULL) failed\n", 7762306a36Sopenharmony_ci strerror(errno)); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Register signal handler for SIGUSR2 */ 8062306a36Sopenharmony_ci ret = sigaction(SIGUSR2, &act, NULL); 8162306a36Sopenharmony_ci if (ret < 0) 8262306a36Sopenharmony_ci ksft_exit_fail_msg( 8362306a36Sopenharmony_ci "%s - sigaction(SIGUSR2, &act, NULL) failed\n", 8462306a36Sopenharmony_ci strerror(errno)); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* Check that CLONE_CLEAR_SIGHAND works. */ 8762306a36Sopenharmony_ci args.flags = CLONE_CLEAR_SIGHAND; 8862306a36Sopenharmony_ci pid = sys_clone3(&args, sizeof(args)); 8962306a36Sopenharmony_ci if (pid < 0) 9062306a36Sopenharmony_ci ksft_exit_fail_msg("%s - clone3(CLONE_CLEAR_SIGHAND) failed\n", 9162306a36Sopenharmony_ci strerror(errno)); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (pid == 0) { 9462306a36Sopenharmony_ci ret = sigaction(SIGUSR1, NULL, &act); 9562306a36Sopenharmony_ci if (ret < 0) 9662306a36Sopenharmony_ci exit(EXIT_FAILURE); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (act.sa_handler != SIG_DFL) 9962306a36Sopenharmony_ci exit(EXIT_FAILURE); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci ret = sigaction(SIGUSR2, NULL, &act); 10262306a36Sopenharmony_ci if (ret < 0) 10362306a36Sopenharmony_ci exit(EXIT_FAILURE); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (act.sa_handler != SIG_DFL) 10662306a36Sopenharmony_ci exit(EXIT_FAILURE); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci exit(EXIT_SUCCESS); 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci ret = wait_for_pid(pid); 11262306a36Sopenharmony_ci if (ret) 11362306a36Sopenharmony_ci ksft_exit_fail_msg( 11462306a36Sopenharmony_ci "Failed to clear signal handler for child process\n"); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci ksft_test_result_pass("Cleared signal handlers for child process\n"); 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciint main(int argc, char **argv) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci ksft_print_header(); 12262306a36Sopenharmony_ci ksft_set_plan(1); 12362306a36Sopenharmony_ci test_clone3_supported(); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci test_clone3_clear_sighand(); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci return ksft_exit_pass(); 12862306a36Sopenharmony_ci} 129