pidns12.c revision f6d7f09ea8353429d488f586ff9cd9525699e31c
1/* 2* Copyright (c) International Business Machines Corp., 2007 3* This program is free software; you can redistribute it and/or modify 4* it under the terms of the GNU General Public License as published by 5* the Free Software Foundation; either version 2 of the License, or 6* (at your option) any later version. 7* This program is distributed in the hope that it will be useful, 8* but WITHOUT ANY WARRANTY; without even the implied warranty of 9* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 10* the GNU General Public License for more details. 11* You should have received a copy of the GNU General Public License 12* along with this program; if not, write to the Free Software 13* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14* 15*************************************************************************** 16* File: pidns12.c 17* * 18* * Description: 19* * The pidns12.c testcase verifies that siginfo->si_pid is set to 0 20* * if sender (parent process) is not in receiver's namespace. 21* * 22* * Test Assertion & Strategy: 23* * Create a PID namespace container. 24* * Initialise signal handler for SIGUSR1 in container. 25* * Let parent send SIGUSR1 to container. 26* * Check if sender pid is set to 0 from signal info. 27* * 28* * Usage: <for command-line> 29* * pidns12 30* * 31* * History: 32* * DATE NAME DESCRIPTION 33* * 13/11/08 Gowrishankar M Creation of this test. 34* * <gowrishankar.m@in.ibm.com> 35* 36******************************************************************************/ 37#define _GNU_SOURCE 1 38#include <sys/wait.h> 39#include <sys/types.h> 40#include <signal.h> 41#include <string.h> 42#include <stdlib.h> 43#include <unistd.h> 44#include <stdio.h> 45#include <usctest.h> 46#include <test.h> 47#include <libclone.h> 48 49char *TCID = "pidns12"; 50int TST_TOTAL = 1; 51int errno; 52int pipefd[2]; 53 54#define CHILD_PID 1 55#define PARENT_PID 0 56 57/* 58 * cleanup() - performs all ONE TIME cleanup for this test at 59 * completion or premature exit. 60 */ 61void cleanup() 62{ 63 /* Clean the test testcase as LTP wants*/ 64 TEST_CLEANUP; 65 66 /* exit with return code appropriate for results */ 67 tst_exit(); 68} 69 70/* 71 * child_signal_handler() - dummy function for sigaction() 72 */ 73static void child_signal_handler(int sig, siginfo_t *si, void *unused) 74{ 75 /* Recieved SIGUSR1. Check sender pid */ 76 if (si->si_pid == 0) 77 tst_resm(TPASS, "cinit: signalling PID (from other namespace)"\ 78 " is 0 as expected"); 79 else 80 tst_resm(TFAIL, "cinit: signalling PID (from other namespace)"\ 81 " is not 0, but %d.", si->si_pid); 82} 83 84/* 85 * child_fn() - Inside container 86 */ 87int child_fn(void *arg) 88{ 89 struct sigaction sa; 90 pid_t pid, ppid; 91 92 /* Set process id and parent pid */ 93 pid = getpid(); 94 ppid = getppid(); 95 if (pid != CHILD_PID || ppid != PARENT_PID) { 96 tst_resm(TBROK, "cinit: pidns is not created."); 97 cleanup(); 98 } 99 100 /* Close read end of pipe */ 101 close(pipefd[0]); 102 103 /* Set signal handler for SIGUSR1 */ 104 sa.sa_flags = SA_SIGINFO; 105 sigfillset(&sa.sa_mask); 106 sa.sa_sigaction = child_signal_handler; 107 if (sigaction(SIGUSR1, &sa, NULL) == -1) { 108 tst_resm(TBROK, "cinit: sigaction() failed(%s).",\ 109 strerror(errno)); 110 cleanup(); 111 } 112 113 /* Let parent to signal SIGUSR1 */ 114 if (write(pipefd[1], "c:go\0", 5) != 5) { 115 tst_resm(TBROK, "cinit: pipe is broken to write"); 116 cleanup(); 117 } 118 119 sleep(3); 120 121 /* cleanup and exit */ 122 close(pipefd[1]); 123 cleanup(); 124 125 /* Control won't reach below */ 126 exit(0); 127} 128 129 130/*********************************************************************** 131* M A I N 132***********************************************************************/ 133 134int main(int argc, char *argv[]) 135{ 136 int status; 137 pid_t pid, cpid; 138 char buf[5]; 139 140 pid = getpid(); 141 tst_resm(TINFO, "parent: PID is %d", pid); 142 143 /* Create pipe for intercommunication */ 144 if (pipe(pipefd) == -1) { 145 tst_resm(TBROK, "parent: pipe() failed. aborting!"); 146 cleanup(); 147 } 148 149 cpid = ltp_clone_quick(CLONE_NEWPID|SIGCHLD, child_fn, NULL); 150 if (cpid < 0) { 151 tst_resm(TBROK, "parent: clone() failed(%s).",\ 152 strerror(errno)); 153 cleanup(); 154 } 155 156 /* Close write end of pipe */ 157 close(pipefd[1]); 158 159 /* Check if container is ready */ 160 read(pipefd[0], buf, 5); 161 if (strcmp(buf, "c:go") != 0) { 162 tst_resm(TBROK, "parent: container did not respond!"); 163 cleanup(); 164 } 165 166 /* Send SIGUSR1 to container init */ 167 if (kill(cpid, SIGUSR1) == -1) { 168 tst_resm(TBROK, "parent: kill() failed(%s).", strerror(errno)); 169 cleanup(); 170 } 171 172 if (waitpid(cpid, &status, 0) < 0) 173 tst_resm(TWARN, "parent: waitpid() failed(%s).",\ 174 strerror(errno)); 175 176 if (WIFSIGNALED(status) && WTERMSIG(status)) 177 tst_resm(TBROK, "child is terminated by signal(%s)",\ 178 strsignal(WTERMSIG(status))); 179 180 /* Cleanup and exit */ 181 close(pipefd[0]); 182 cleanup(); 183 184 /* Control won't reach below */ 185 exit(0); 186 187} /* End main */ 188