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