1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2007 4 * 13/11/08 Gowrishankar M <gowrishankar.m@in.ibm.com> 5 * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 6 */ 7 8/*\ 9 * [Description] 10 * 11 * Clone a process with CLONE_NEWPID flag, block SIGUSR1 signal before sending 12 * it from parent and check if it's received once SIGUSR1 signal is unblocked. 13 */ 14 15#define _GNU_SOURCE 1 16#include <signal.h> 17#include "tst_test.h" 18#include "lapi/sched.h" 19 20static volatile int signals; 21static volatile int last_signo; 22 23static void child_signal_handler(LTP_ATTRIBUTE_UNUSED int sig, siginfo_t *si, LTP_ATTRIBUTE_UNUSED void *unused) 24{ 25 last_signo = si->si_signo; 26 signals++; 27} 28 29static void child_func(void) 30{ 31 struct sigaction sa; 32 sigset_t newset; 33 pid_t cpid, ppid; 34 35 cpid = tst_getpid(); 36 ppid = getppid(); 37 38 if (cpid != 1 || ppid != 0) { 39 tst_res(TFAIL, "Got unexpected result of cpid=%d ppid=%d", cpid, ppid); 40 return; 41 } 42 43 SAFE_SIGEMPTYSET(&newset); 44 SAFE_SIGADDSET(&newset, SIGUSR1); 45 SAFE_SIGPROCMASK(SIG_BLOCK, &newset, 0); 46 47 TST_CHECKPOINT_WAKE_AND_WAIT(0); 48 49 sa.sa_flags = SA_SIGINFO; 50 SAFE_SIGFILLSET(&sa.sa_mask); 51 sa.sa_sigaction = child_signal_handler; 52 53 SAFE_SIGACTION(SIGUSR1, &sa, NULL); 54 55 SAFE_SIGPROCMASK(SIG_UNBLOCK, &newset, 0); 56 57 if (signals != 1) { 58 tst_res(TFAIL, "Received %d signals", signals); 59 return; 60 } 61 62 if (last_signo != SIGUSR1) { 63 tst_res(TFAIL, "Received %s signal", tst_strsig(last_signo)); 64 return; 65 } 66 67 tst_res(TPASS, "Received SIGUSR1 signal after unblock"); 68} 69 70static void run(void) 71{ 72 const struct tst_clone_args args = { 73 .flags = CLONE_NEWPID, 74 .exit_signal = SIGCHLD, 75 }; 76 int pid; 77 78 pid = SAFE_CLONE(&args); 79 if (!pid) { 80 child_func(); 81 return; 82 } 83 84 TST_CHECKPOINT_WAIT(0); 85 86 SAFE_KILL(pid, SIGUSR1); 87 88 TST_CHECKPOINT_WAKE(0); 89} 90 91static struct tst_test test = { 92 .test_all = run, 93 .needs_root = 1, 94 .forks_child = 1, 95 .needs_checkpoints = 1, 96 .needs_kconfigs = (const char *[]) { 97 "CONFIG_PID_NS", 98 NULL, 99 }, 100}; 101