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