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