blob: 0eac1152a2798b88ec84d0cccca97b751777e19d [file] [log] [blame]
subrata_modak3a14aff2008-12-12 13:17:07 +00001/*
2* Copyright (c) Bull S.A.S. 2008
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: pidns31.c
17*
18* Description:
19* This testcase checks if the si_pid is correctly set when a process
20* that has registered for notification on a posix mqueue is in an
21* ancestor namespace wrt the process that sends a message to that posix
22* mqueue.
23*
24* Test Assertion & Strategy:
25* Parent Child
26* --------------------------------------------------------------------------
27* Create a POSIX mqueue.
28* Create a PID namespace container.
29* Register for notification when a
30* message arrives in that mqueue
31* Install a handler for SIGUSR1.
32* Open that mqueue for writing
33* Write something to the mqueue.
34* Inside the handler, check that
35* si_pid is set to the child's pid
36*
37* Usage: <for command-line>
38* pidns31
39*
40* History:
41* DATE NAME DESCRIPTION
42* 04/12/08 Nadia Derbey Creation of this test.
43* <Nadia.Derbey@bull.net>
44*
45******************************************************************************/
yaberauneyabe3fdcf2009-11-14 17:52:51 +000046#ifndef _GNU_SOURCE
47#define _GNU_SOURCE
48#endif
subrata_modak3a14aff2008-12-12 13:17:07 +000049#include <sys/wait.h>
50#include <sys/types.h>
51#include <signal.h>
52#include <stdlib.h>
53#include <unistd.h>
54#include <stdio.h>
55#include <mqueue.h>
yaberauneyabe3fdcf2009-11-14 17:52:51 +000056#include "usctest.h"
57#include "test.h"
yaberauneya3e8f77b2009-11-14 23:58:26 +000058#include "linux_syscall_numbers.h"
yaberauneyabe3fdcf2009-11-14 17:52:51 +000059#include "libclone.h"
subrata_modak3a14aff2008-12-12 13:17:07 +000060
61char *TCID = "pidns31";
62int TST_TOTAL = 1;
63
Garrett Coopercb2dde72010-11-11 00:38:43 -080064char *mqname = "mq1";
subrata_modak3a14aff2008-12-12 13:17:07 +000065int result = TFAIL;
66
67int errno;
68int father_to_child[2];
69
70#define CHILD_PID 1
71#define PARENT_PID 0
72
73#define MSG "HOW ARE YOU"
74#define MSG_PRIO 1
75
76#define NO_STEP -1
77#define F_STEP_0 0x00
78#define F_STEP_1 0x01
79#define F_STEP_2 0x02
80#define F_STEP_3 0x03
81#define C_STEP_0 0x10
82#define C_STEP_1 0x11
83
84struct notify_info {
85 mqd_t mqd;
86 pid_t pid;
87};
88
89static void remove_pipe(int *fd)
90{
91 close(fd[0]);
92 close(fd[1]);
93}
94
95static void remove_mqueue(mqd_t mqd)
96{
yaberauneya3e8f77b2009-11-14 23:58:26 +000097 mq_close(mqd);
yaberauneyabe3fdcf2009-11-14 17:52:51 +000098 syscall(__NR_mq_unlink, mqname);
subrata_modak3a14aff2008-12-12 13:17:07 +000099}
100
101/*
102 * steps F_STEP_XX : called from main
103 * steps C_STEP_XX : called from child_fn
104 */
105static void cleanup_resources(int step, mqd_t mqd)
106{
107 switch (step) {
108 case C_STEP_1:
109 close(father_to_child[0]);
110 /* fall through */
111 case C_STEP_0:
yaberauneya3e8f77b2009-11-14 23:58:26 +0000112 mq_close(mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000113 break;
114
115 case F_STEP_3:
116 remove_mqueue(mqd);
117 close(father_to_child[1]);
118 break;
119
120 case F_STEP_2:
yaberauneyabe3fdcf2009-11-14 17:52:51 +0000121 syscall(__NR_mq_notify, mqd, NULL);
subrata_modak3a14aff2008-12-12 13:17:07 +0000122 /* fall through */
123 case F_STEP_1:
124 remove_mqueue(mqd);
125 /* fall through */
126 case F_STEP_0:
127 remove_pipe(father_to_child);
128 break;
129 default:
130 tst_resm(TWARN, "Unknown code - no resource removed.");
131 break;
132 }
133}
134
135/*
yaberauneya3e8f77b2009-11-14 23:58:26 +0000136 * cleanup_mqueue() - performs all ONE TIME cleanup for this test at
subrata_modak3a14aff2008-12-12 13:17:07 +0000137 * completion or premature exit.
138 * step == -1 means no local resource to remove.
139 */
yaberauneya3e8f77b2009-11-14 23:58:26 +0000140void cleanup_mqueue(int result, int step, mqd_t mqd)
subrata_modak3a14aff2008-12-12 13:17:07 +0000141{
142 if (step != NO_STEP)
143 cleanup_resources(step, mqd);
144
145 /* Clean the test testcase as LTP wants*/
146 TEST_CLEANUP;
147
subrata_modak88c166c2009-06-09 16:01:20 +0000148 tst_exit();
subrata_modak3a14aff2008-12-12 13:17:07 +0000149}
150
151/*
152 * child_fn() - Inside container
153 */
154int child_fn(void *arg)
155{
156 pid_t pid, ppid;
157 mqd_t mqd;
158 char buf[5];
159
160 /* Set process id and parent pid */
161 pid = getpid();
162 ppid = getppid();
163
164 if (pid != CHILD_PID || ppid != PARENT_PID) {
165 tst_resm(TBROK, "cinit: pidns is not created");
yaberauneya3e8f77b2009-11-14 23:58:26 +0000166 cleanup_mqueue(TBROK, NO_STEP, 0);
subrata_modak3a14aff2008-12-12 13:17:07 +0000167 }
168
169 /* Close the appropriate end of pipe */
170 close(father_to_child[1]);
171
172 /* Is parent ready to receive a message? */
173 read(father_to_child[0], buf, 5);
174 if (strcmp(buf, "f:ok")) {
175 tst_resm(TBROK, "cinit: parent did not send the message!");
yaberauneya3e8f77b2009-11-14 23:58:26 +0000176 cleanup_mqueue(TBROK, NO_STEP, 0);
subrata_modak3a14aff2008-12-12 13:17:07 +0000177 }
178 tst_resm(TINFO, "cinit: my father is ready to receive a message");
179
yaberauneyabe3fdcf2009-11-14 17:52:51 +0000180 mqd = syscall(__NR_mq_open, mqname, O_WRONLY);
subrata_modak3a14aff2008-12-12 13:17:07 +0000181 if (mqd == (mqd_t)-1) {
182 tst_resm(TBROK, "cinit: mq_open() failed (%s)",
183 strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000184 cleanup_mqueue(TBROK, NO_STEP, 0);
subrata_modak3a14aff2008-12-12 13:17:07 +0000185 }
186 tst_resm(TINFO, "cinit: mq_open succeeded");
187
yaberauneya3e8f77b2009-11-14 23:58:26 +0000188 if (mq_send(mqd, MSG, strlen(MSG), MSG_PRIO) ==
yaberauneyabe3fdcf2009-11-14 17:52:51 +0000189 (mqd_t)-1) {
subrata_modak3a14aff2008-12-12 13:17:07 +0000190 tst_resm(TBROK, "cinit: mq_send() failed (%s)",
191 strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000192 cleanup_mqueue(TBROK, C_STEP_0, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000193 }
194 tst_resm(TINFO, "cinit: mq_send() succeeded");
195
196 /* Cleanup and exit */
197 cleanup_resources(C_STEP_1, mqd);
198 exit(0);
199}
200
201/*
202 * father_signal_handler()
203 */
204static void father_signal_handler(int sig, siginfo_t *si, void *unused)
205{
206 char buf[256];
207 struct mq_attr attr;
208 struct notify_info *info;
209
210 if (si->si_signo != SIGUSR1) {
211 tst_resm(TBROK, "father: received %s unexpectedly",
212 strsignal(si->si_signo));
213 return;
214 }
215
216 if (si->si_code != SI_MESGQ) {
217 tst_resm(TBROK, "father: expected signal code SI_MESGQ - "
218 "Got %d", si->si_code);
219 return;
220 }
221
222 if (!si->si_ptr) {
223 tst_resm(TBROK, "father: expected si_ptr - Got NULL");
224 return;
225 }
226
227 info = (struct notify_info *)si->si_ptr;
228
229 if (si->si_pid != info->pid) {
230 tst_resm(TFAIL,
231 "father: expected signal originator PID = %d - Got %d",
232 info->pid, si->si_pid);
233 return;
234 }
235
236 tst_resm(TPASS, "father: signal originator PID = %d", si->si_pid);
237 result = TPASS;
238
239 /*
240 * Now read the message - Be silent on errors since this is not the
241 * test purpose.
242 */
yaberauneya3e8f77b2009-11-14 23:58:26 +0000243 if (!mq_getattr(info->mqd, &attr))
244 mq_receive(info->mqd, buf, attr.mq_msgsize, NULL);
subrata_modak3a14aff2008-12-12 13:17:07 +0000245}
246
247/***********************************************************************
248* M A I N
249***********************************************************************/
250
251int main(int argc, char *argv[])
252{
subrata_modak3a14aff2008-12-12 13:17:07 +0000253 pid_t cpid;
254 mqd_t mqd;
255 struct sigevent notif;
256 struct sigaction sa;
257 int status;
258 struct notify_info info;
259
subrata_modak3a14aff2008-12-12 13:17:07 +0000260 if (pipe(father_to_child) == -1) {
261 tst_resm(TBROK, "parent: pipe() failed. aborting!");
yaberauneya3e8f77b2009-11-14 23:58:26 +0000262 cleanup_mqueue(TBROK, NO_STEP, 0);
subrata_modak3a14aff2008-12-12 13:17:07 +0000263 }
264
yaberauneyabe3fdcf2009-11-14 17:52:51 +0000265 syscall(__NR_mq_unlink, mqname);
266 mqd = syscall(__NR_mq_open, mqname, O_RDWR|O_CREAT|O_EXCL, 0777, NULL);
subrata_modak3a14aff2008-12-12 13:17:07 +0000267 if (mqd == (mqd_t)-1) {
268 tst_resm(TBROK, "parent: mq_open() failed (%s)",
269 strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000270 cleanup_mqueue(TBROK, F_STEP_0, 0);
subrata_modak3a14aff2008-12-12 13:17:07 +0000271 }
272 tst_resm(TINFO, "parent: successfully created posix mqueue");
273
274 /* container creation on PID namespace */
vapierf6d7f092009-11-03 20:07:35 +0000275 cpid = ltp_clone_quick(CLONE_NEWPID|SIGCHLD, child_fn, NULL);
subrata_modak3a14aff2008-12-12 13:17:07 +0000276 if (cpid < 0) {
277 tst_resm(TBROK, "parent: clone() failed(%s)", strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000278 cleanup_mqueue(TBROK, F_STEP_1, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000279 }
280 tst_resm(TINFO, "parent: successfully created child (pid = %d)", cpid);
281
282 /* Register for notification on message arrival */
283 notif.sigev_notify = SIGEV_SIGNAL;
284 notif.sigev_signo = SIGUSR1;
285 info.mqd = mqd;
286 info.pid = cpid;
287 notif.sigev_value.sival_ptr = &info;
yaberauneyabe3fdcf2009-11-14 17:52:51 +0000288 if (syscall(__NR_mq_notify, mqd, &notif) == (mqd_t)-1) {
subrata_modak3a14aff2008-12-12 13:17:07 +0000289 tst_resm(TBROK, "parent: mq_notify() failed (%s)",
290 strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000291 cleanup_mqueue(TBROK, F_STEP_1, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000292 }
293 tst_resm(TINFO, "parent: successfully registered for notification");
294
295 /* Define handler for SIGUSR1 */
296 sa.sa_flags = SA_SIGINFO;
297 sigemptyset(&sa.sa_mask);
298 sa.sa_sigaction = father_signal_handler;
299 if (sigaction(SIGUSR1, &sa, NULL) == -1) {
300 tst_resm(TBROK, "parent: sigaction() failed(%s)",
301 strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000302 cleanup_mqueue(TBROK, F_STEP_2, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000303 }
304 tst_resm(TINFO, "parent: successfully registered handler for SIGUSR1");
305
306 /* Close the appropriate end of pipe */
307 close(father_to_child[0]);
308
309 /* Tell the child a message can be sent */
310 if (write(father_to_child[1], "f:ok", 5) != 5) {
311 tst_resm(TBROK, "parent: pipe is broken(%s)", strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000312 cleanup_mqueue(TBROK, F_STEP_2, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000313 }
314
315 sleep(3);
316
317 /* Wait for child to finish */
318 if (wait(&status) == -1) {
319 tst_resm(TBROK, "parent: wait() failed(%s)", strerror(errno));
yaberauneya3e8f77b2009-11-14 23:58:26 +0000320 cleanup_mqueue(TBROK, F_STEP_1, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000321 }
322
yaberauneya3e8f77b2009-11-14 23:58:26 +0000323 cleanup_mqueue(result, F_STEP_3, mqd);
subrata_modak3a14aff2008-12-12 13:17:07 +0000324
Garrett Cooper2c282152010-12-16 00:55:50 -0800325 tst_exit();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700326}