• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "pidns_helper.h"
46 #include "test.h"
47 
48 char *TCID = "pidns12";
49 int TST_TOTAL = 1;
50 int pipefd[2];
51 
52 #define CHILD_PID       1
53 #define PARENT_PID      0
54 
55 /*
56  * child_signal_handler() - dummy function for sigaction()
57  */
child_signal_handler(int sig,siginfo_t * si,void * unused)58 static void child_signal_handler(int sig, siginfo_t * si, void *unused)
59 {
60 	/* Recieved SIGUSR1. Check sender pid */
61 	if (si->si_pid == 0)
62 		tst_resm(TPASS, "cinit: signalling PID (from other namespace)"
63 			 " is 0 as expected");
64 	else
65 		tst_resm(TFAIL, "cinit: signalling PID (from other namespace)"
66 			 " is not 0, but %d.", si->si_pid);
67 }
68 
69 /*
70  * child_fn() - Inside container
71  */
child_fn(void * arg)72 int child_fn(void *arg)
73 {
74 	struct sigaction sa;
75 	pid_t pid, ppid;
76 
77 	/* Set process id and parent pid */
78 	pid = getpid();
79 	ppid = getppid();
80 	if (pid != CHILD_PID || ppid != PARENT_PID) {
81 		tst_resm(TBROK, "cinit: pidns is not created.");
82 	}
83 
84 	/* Close read end of pipe */
85 	close(pipefd[0]);
86 
87 	/* Set signal handler for SIGUSR1 */
88 	sa.sa_flags = SA_SIGINFO;
89 	sigfillset(&sa.sa_mask);
90 	sa.sa_sigaction = child_signal_handler;
91 	if (sigaction(SIGUSR1, &sa, NULL) == -1) {
92 		tst_resm(TBROK, "cinit: sigaction() failed(%s).",
93 			 strerror(errno));
94 	}
95 
96 	/* Let parent to signal SIGUSR1 */
97 	if (write(pipefd[1], "c:go\0", 5) != 5) {
98 		tst_resm(TBROK, "cinit: pipe is broken to write");
99 	}
100 
101 	sleep(3);
102 
103 	/* cleanup and exit */
104 	close(pipefd[1]);
105 
106 	/* Control won't reach below */
107 	exit(0);
108 }
109 
setup(void)110 static void setup(void)
111 {
112 	tst_require_root();
113 	check_newpid();
114 }
115 
116 /***********************************************************************
117 *   M A I N
118 ***********************************************************************/
119 
main(int argc,char * argv[])120 int main(int argc, char *argv[])
121 {
122 	int status;
123 	pid_t pid, cpid;
124 	char buf[5];
125 
126 	setup();
127 
128 	pid = getpid();
129 	tst_resm(TINFO, "parent: PID is %d", pid);
130 
131 	/* Create pipe for intercommunication */
132 	if (pipe(pipefd) == -1) {
133 		tst_resm(TBROK, "parent: pipe() failed. aborting!");
134 	}
135 
136 	cpid = ltp_clone_quick(CLONE_NEWPID | SIGCHLD, child_fn, NULL);
137 	if (cpid < 0) {
138 		tst_resm(TBROK, "parent: clone() failed(%s).", strerror(errno));
139 	}
140 
141 	/* Close write end of pipe */
142 	close(pipefd[1]);
143 
144 	/* Check if container is ready */
145 	read(pipefd[0], buf, 5);
146 	if (strcmp(buf, "c:go") != 0) {
147 		tst_resm(TBROK, "parent: container did not respond!");
148 	}
149 
150 	/* Send SIGUSR1 to container init */
151 	if (kill(cpid, SIGUSR1) == -1) {
152 		tst_resm(TBROK, "parent: kill() failed(%s).", strerror(errno));
153 	}
154 
155 	if (waitpid(cpid, &status, 0) < 0)
156 		tst_resm(TWARN, "parent: waitpid() failed(%s).",
157 			 strerror(errno));
158 
159 	if (WIFSIGNALED(status) && WTERMSIG(status))
160 		tst_resm(TBROK, "child is terminated by signal(%s)",
161 			 strsignal(WTERMSIG(status)));
162 
163 	/* Cleanup and exit */
164 	close(pipefd[0]);
165 
166 	/* Control won't reach below */
167 	exit(0);
168 
169 }
170