blob: 479069559259146a555de2038f5d5c0e9b7027b4 [file] [log] [blame]
Matus Marhefka20ddcf82014-10-02 16:47:59 +02001/* Copyright (c) 2014 Red Hat, Inc.
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of version 2 the GNU General Public License as
5 * published by the Free Software Foundation.
6 *
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 the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 ***********************************************************************
15 * File: msg_comm.c
16 *
17 * Description:
18 * 1. Clones two child processes with CLONE_NEWIPC flag, each child
19 * gets System V message queue (msg) with the _identical_ key.
20 * 2. Child1 appends a message with identifier #1 to the message queue.
21 * 3. Child2 appends a message with identifier #2 to the message queue.
22 * 4. Appends to the message queue with the identical key but from
23 * two different IPC namespaces should not interfere with each other
24 * and so child1 checks whether its message queue doesn't contain
25 * a message with identifier #2, if it doesn't test passes, otherwise
26 * test fails.
27 */
28
29#define _GNU_SOURCE
30#include <sys/ipc.h>
31#include <sys/msg.h>
32#include <sys/types.h>
33#include <sys/wait.h>
34#include <stdio.h>
35#include <errno.h>
Matus Marhefka20ddcf82014-10-02 16:47:59 +020036#include "test.h"
37#include "safe_macros.h"
38#include "libclone.h"
39#include "ipcns_helper.h"
40
41
42#define TESTKEY 124426L
43#define MSGSIZE 50
44char *TCID = "msg_comm";
45int TST_TOTAL = 1;
46struct tst_checkpoint checkpoint1;
47struct tst_checkpoint checkpoint2;
48struct sysv_msg {
49 long mtype;
50 char mtext[MSGSIZE];
51};
52
53
54static void cleanup(void)
55{
56 tst_rmdir();
57}
58
59static void setup(void)
60{
61 tst_require_root(NULL);
62 check_newipc();
63 tst_tmpdir();
64 TST_CHECKPOINT_CREATE(&checkpoint1);
65 TST_CHECKPOINT_CREATE(&checkpoint2);
66}
67
68int chld1_msg(void *arg)
69{
70 int id, n, rval = 0;
71 struct sysv_msg m;
72 struct sysv_msg rec;
73
74 id = msgget(TESTKEY, IPC_CREAT | 0600);
75 if (id == -1) {
76 perror("msgget");
77 return 2;
78 }
79
80 m.mtype = 1;
81 m.mtext[0] = 'A';
82 if (msgsnd(id, &m, sizeof(struct sysv_msg) - sizeof(long), 0) == -1) {
83 perror("msgsnd");
84 msgctl(id, IPC_RMID, NULL);
85 return 2;
86 }
87
88 /* wait for child2 to write into the message queue */
89 TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
90
91 /* if child1 message queue has changed (by child2) report fail */
92 n = msgrcv(id, &rec, sizeof(struct sysv_msg) - sizeof(long),
93 2, IPC_NOWAIT);
94 if (n == -1 && errno != ENOMSG) {
95 perror("msgrcv");
96 msgctl(id, IPC_RMID, NULL);
97 return 2;
98 }
99 /* if mtype #2 was found in the message queue, it is fail */
100 if (n > 0) {
101 rval = 1;
102 }
103
104 /* tell child2 to continue */
105 TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
106
107 msgctl(id, IPC_RMID, NULL);
108 return rval;
109}
110
111int chld2_msg(void *arg)
112{
113 int id;
114 struct sysv_msg m;
115
116 id = msgget(TESTKEY, IPC_CREAT | 0600);
117 if (id == -1) {
118 perror("msgget");
119 return 2;
120 }
121
122 m.mtype = 2;
123 m.mtext[0] = 'B';
124 if (msgsnd(id, &m, sizeof(struct sysv_msg) - sizeof(long), 0) == -1) {
125 perror("msgsnd");
126 msgctl(id, IPC_RMID, NULL);
127 return 2;
128 }
129
130 /* tell child1 to continue */
131 TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint2);
132
133 /* wait for child1 */
134 TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
135
136 msgctl(id, IPC_RMID, NULL);
137 return 0;
138}
139
140static void test(void)
141{
142 int status, ret = 0;
143
144 ret = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_msg, NULL);
145 if (ret == -1)
146 tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
147
148 ret = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_msg, NULL);
149 if (ret == -1)
150 tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
151
152
153 while (wait(&status) > 0) {
154 if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
155 ret = 1;
156 if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
157 tst_brkm(TBROK | TERRNO, cleanup, "error in child");
158 if (WIFSIGNALED(status)) {
159 tst_resm(TFAIL, "child was killed with signal %s",
160 tst_strsig(WTERMSIG(status)));
161 return;
162 }
163 }
164
165 if (ret)
166 tst_resm(TFAIL, "SysV msg: communication with identical keys"
167 " between namespaces");
168 else
169 tst_resm(TPASS, "SysV msg: communication with identical keys"
170 " between namespaces");
171}
172
173int main(int argc, char *argv[])
174{
175 const char *msg;
176 int lc;
177
178 msg = parse_opts(argc, argv, NULL, NULL);
179 if (msg != NULL)
180 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
181
182 setup();
183
184 for (lc = 0; TEST_LOOPING(lc); lc++)
185 test();
186
187 cleanup();
188 tst_exit();
189}