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