1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2007
4f08c3bdfSopenharmony_ci * Copyright (c) SUSE LLC 2021
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * History:
7f08c3bdfSopenharmony_ci * 23/10/08  Gowrishankar M 			Created test scenarion.
8f08c3bdfSopenharmony_ci *            <gowrishankar.m@in.ibm.com>
9f08c3bdfSopenharmony_ci */
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ci/*\
12f08c3bdfSopenharmony_ci * [Description]
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * The pidns13.c testcase checks container init, for async I/O
15f08c3bdfSopenharmony_ci * triggered by peer namespace process.
16f08c3bdfSopenharmony_ci *
17f08c3bdfSopenharmony_ci * [Algorithm]
18f08c3bdfSopenharmony_ci * * create a pipe in parent namespace
19f08c3bdfSopenharmony_ci * * create two PID namespace containers(cinit1 and cinit2)
20f08c3bdfSopenharmony_ci * * in cinit1, set pipe read end to send SIGUSR1 for asynchronous I/O
21f08c3bdfSopenharmony_ci * * let cinit2 trigger async I/O on pipe write end
22f08c3bdfSopenharmony_ci * * in signal info, check si_code to be POLL_IN and si_fd to be pipe read fd
23f08c3bdfSopenharmony_ci */
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1
26f08c3bdfSopenharmony_ci#include <sys/wait.h>
27f08c3bdfSopenharmony_ci#include <sys/types.h>
28f08c3bdfSopenharmony_ci#include <fcntl.h>
29f08c3bdfSopenharmony_ci#include <signal.h>
30f08c3bdfSopenharmony_ci#include <stdlib.h>
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ci#include "tst_test.h"
33f08c3bdfSopenharmony_ci#include "tst_clone.h"
34f08c3bdfSopenharmony_ci#include "lapi/sched.h"
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic int pipe_fd[2];
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#define CHILD_PID       1
39f08c3bdfSopenharmony_ci#define PARENT_PID      0
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_cistatic void child_signal_handler(int sig, siginfo_t *si,
42f08c3bdfSopenharmony_ci				 void *unused LTP_ATTRIBUTE_UNUSED)
43f08c3bdfSopenharmony_ci{
44f08c3bdfSopenharmony_ci	tst_res(TWARN, "cinit(pid %d): Caught signal! sig=%d, si_fd=%d, si_code=%d",
45f08c3bdfSopenharmony_ci		tst_getpid(), sig, si->si_fd, si->si_code);
46f08c3bdfSopenharmony_ci}
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistatic void child_fn(unsigned int cinit_no)
49f08c3bdfSopenharmony_ci{
50f08c3bdfSopenharmony_ci	struct sigaction sa;
51f08c3bdfSopenharmony_ci	sigset_t newset;
52f08c3bdfSopenharmony_ci	siginfo_t info;
53f08c3bdfSopenharmony_ci	struct timespec timeout;
54f08c3bdfSopenharmony_ci	pid_t pid, ppid;
55f08c3bdfSopenharmony_ci	int flags;
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	pid = tst_getpid();
58f08c3bdfSopenharmony_ci	ppid = getppid();
59f08c3bdfSopenharmony_ci	if (pid != CHILD_PID || ppid != PARENT_PID)
60f08c3bdfSopenharmony_ci		tst_brk(TBROK, "cinit%u: pidns not created.", cinit_no);
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	if (cinit_no == 1) {
63f08c3bdfSopenharmony_ci		SAFE_CLOSE(pipe_fd[1]);
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci		sigemptyset(&newset);
66f08c3bdfSopenharmony_ci		sigaddset(&newset, SIGUSR1);
67f08c3bdfSopenharmony_ci		SAFE_SIGPROCMASK(SIG_BLOCK, &newset, NULL);
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci		SAFE_FCNTL(pipe_fd[0], F_SETOWN, pid);
70f08c3bdfSopenharmony_ci		SAFE_FCNTL(pipe_fd[0], F_SETSIG, SIGUSR1);
71f08c3bdfSopenharmony_ci		flags = SAFE_FCNTL(pipe_fd[0], F_GETFL);
72f08c3bdfSopenharmony_ci		SAFE_FCNTL(pipe_fd[0], F_SETFL, flags | O_ASYNC);
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci		sa.sa_flags = SA_SIGINFO;
75f08c3bdfSopenharmony_ci		sigfillset(&sa.sa_mask);
76f08c3bdfSopenharmony_ci		sa.sa_sigaction = child_signal_handler;
77f08c3bdfSopenharmony_ci		SAFE_SIGACTION(SIGUSR1, &sa, NULL);
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci		TST_CHECKPOINT_WAKE(1);
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci		timeout.tv_sec = 10;
82f08c3bdfSopenharmony_ci		timeout.tv_nsec = 0;
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci		if (sigtimedwait(&newset, &info, &timeout) != SIGUSR1) {
85f08c3bdfSopenharmony_ci			tst_brk(TBROK | TERRNO,
86f08c3bdfSopenharmony_ci				"cinit1: sigtimedwait() failed.");
87f08c3bdfSopenharmony_ci		}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci		if (info.si_fd == pipe_fd[0] && info.si_code == POLL_IN)
90f08c3bdfSopenharmony_ci			tst_res(TPASS, "cinit1: si_fd is %d, si_code is %d",
91f08c3bdfSopenharmony_ci				info.si_fd, info.si_code);
92f08c3bdfSopenharmony_ci		else
93f08c3bdfSopenharmony_ci			tst_res(TFAIL, "cinit1: si_fd is %d, si_code is %d",
94f08c3bdfSopenharmony_ci				info.si_fd, info.si_code);
95f08c3bdfSopenharmony_ci	} else {
96f08c3bdfSopenharmony_ci		SAFE_CLOSE(pipe_fd[0]);
97f08c3bdfSopenharmony_ci
98f08c3bdfSopenharmony_ci		TST_CHECKPOINT_WAIT(1);
99f08c3bdfSopenharmony_ci		SAFE_WRITE(SAFE_WRITE_ALL, pipe_fd[1], "test\n", 5);
100f08c3bdfSopenharmony_ci	}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci	exit(0);
103f08c3bdfSopenharmony_ci}
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_cistatic void run(void)
106f08c3bdfSopenharmony_ci{
107f08c3bdfSopenharmony_ci	const struct tst_clone_args cargs = {
108f08c3bdfSopenharmony_ci		.flags = CLONE_NEWPID,
109f08c3bdfSopenharmony_ci		.exit_signal = SIGCHLD,
110f08c3bdfSopenharmony_ci	};
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	SAFE_PIPE(pipe_fd);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	if (!SAFE_CLONE(&cargs))
115f08c3bdfSopenharmony_ci		child_fn(1);
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	if (!SAFE_CLONE(&cargs))
118f08c3bdfSopenharmony_ci		child_fn(2);
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	SAFE_CLOSE(pipe_fd[0]);
121f08c3bdfSopenharmony_ci	SAFE_CLOSE(pipe_fd[1]);
122f08c3bdfSopenharmony_ci}
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_cistatic struct tst_test test = {
125f08c3bdfSopenharmony_ci	.test_all = run,
126f08c3bdfSopenharmony_ci	.needs_root = 1,
127f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
128f08c3bdfSopenharmony_ci	.forks_child = 1,
129f08c3bdfSopenharmony_ci};
130