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