1 /* *************************************************************************
2 * Copyright (c) International Business Machines Corp., 2009
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 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 * the GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 * Author: Veerendra C <vechandr@in.ibm.com>
17 *
18 * Test Assertion:
19 * This testcase verifies the semaphore isoloation in 2 diff containers.
20 * It tries to create/access a semaphore created with the same KEY.
21 *
22 * Description:
23 * Create 2 'containers' with the below flag value
24 * Flag = clone, clone(CLONE_NEWIPC), or unshare(CLONE_NEWIPC)
25 * In Cont1, create semaphore with key 124326L
26 * In Cont2, try to access the semaphore created in Cont1.
27 * PASS :
28 * If flag = None and the semaphore is accessible in Cont2.
29 * If flag = unshare/clone and the semaphore is not accessible in Cont2.
30 * If semaphore is not accessible in Cont2, creates new semaphore with
31 * the same key to double check isloation in IPCNS.
32 *
33 * FAIL :
34 * If flag = none and the semaphore is not accessible.
35 * If flag = unshare/clone and semaphore is accessible in Cont2.
36 * If the new semaphore creation Fails.
37 ***************************************************************************/
38
39 #define _GNU_SOURCE 1
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <sys/ipc.h>
45 #include <sys/sem.h>
46 #include <libclone.h>
47 #include "test.h"
48 #include "ipcns_helper.h"
49
50 #define MY_KEY 124326L
51 #define UNSHARESTR "unshare"
52 #define CLONESTR "clone"
53 #define NONESTR "none"
54
55 char *TCID = "semtest_2ns";
56 int TST_TOTAL = 1;
57 int p1[2];
58 int p2[2];
59 static struct sembuf semop_lock[2] = {
60 /* sem_num, sem_op, flag */
61 {0, 0, 0}, /* wait for sem#0 to become 0 */
62 {0, 1, SEM_UNDO} /* then increment sem#0 by 1 */
63 };
64
65 static struct sembuf semop_unlock[1] = {
66 /* sem_num, sem_op, flag */
67 {0, -1, (IPC_NOWAIT | SEM_UNDO)} /* decrement sem#0 by 1 (sets it to 0) */
68 };
69
70 /*
71 * sem_lock() - Locks the semaphore for crit-sec updation, and unlocks it later
72 */
sem_lock(int id)73 void sem_lock(int id)
74 {
75 /* Checking the semlock and simulating as if the crit-sec is updated */
76 if (semop(id, &semop_lock[0], 2) < 0) {
77 perror("sem lock error");
78 tst_brkm(TBROK, NULL, "semop failed");
79 }
80 tst_resm(TINFO, "Sem1: File locked, Critical section is updated...");
81 sleep(2);
82 if (semop(id, &semop_unlock[0], 1) < 0) {
83 perror("sem unlock error");
84 tst_brkm(TBROK, NULL, "semop failed");
85 }
86 }
87
88 /*
89 * check_sem1 - does not read -- it writes to check_sem2() when it's done.
90 */
check_sem1(void * vtest)91 int check_sem1(void *vtest)
92 {
93 int id1;
94
95 (void) vtest;
96
97 close(p1[0]);
98 /* 1. Create (or fetch if existing) the binary semaphore */
99 id1 = semget(MY_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
100 if (id1 == -1) {
101 perror("Semaphore create");
102 if (errno != EEXIST) {
103 perror("semget failure");
104 tst_brkm(TBROK, NULL, "semget failure");
105 }
106 id1 = semget(MY_KEY, 1, 0);
107 if (id1 == -1) {
108 perror("Semaphore create");
109 tst_brkm(TBROK, NULL, "semget failure");
110 }
111 }
112
113 write(p1[1], "go", 3);
114 tst_resm(TINFO, "Cont1: Able to create semaphore");
115 tst_exit();
116 }
117
118 /*
119 * check_sem2() reads from check_sem1() and writes to main() when it's done.
120 */
121
check_sem2(void * vtest)122 int check_sem2(void *vtest)
123 {
124 char buf[3];
125 int id2;
126
127 (void) vtest;
128
129 close(p1[1]);
130 close(p2[0]);
131 read(p1[0], buf, 3);
132
133 id2 = semget(MY_KEY, 1, 0);
134 if (id2 != -1) {
135 sem_lock(id2);
136 write(p2[1], "exists", 7);
137 } else {
138 /* Trying to create a new semaphore, if semaphore is not existing */
139 id2 = semget(MY_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
140 if (id2 == -1) {
141 perror("Semaphore create");
142 if (errno != EEXIST) {
143 perror("semget failure");
144 tst_resm(TBROK, "semget failure");
145 }
146 } else
147 tst_resm(TINFO,
148 "Cont2: Able to create semaphore with sameKey");
149 /* Passing the pipe Not-found mesg */
150 write(p2[1], "notfnd", 7);
151 }
152
153 tst_exit();
154 }
155
setup(void)156 static void setup(void)
157 {
158 tst_require_root();
159 check_newipc();
160 }
161
main(int argc,char * argv[])162 int main(int argc, char *argv[])
163 {
164 int ret, id, use_clone = T_NONE;
165 char *tsttype = NONESTR;
166 char buf[7];
167
168 setup();
169
170 if (argc != 2) {
171 tst_resm(TINFO, "Usage: %s <clone| unshare| none>", argv[0]);
172 tst_resm(TINFO, " where clone, unshare, or fork specifies"
173 " unshare method.");
174 tst_exit();
175 }
176
177 /* Using PIPE's to sync between container and Parent */
178 if (pipe(p1) == -1) {
179 perror("pipe1");
180 tst_exit();
181 }
182 if (pipe(p2) == -1) {
183 perror("pipe2");
184 tst_exit();
185 }
186
187 if (strcmp(argv[1], "clone") == 0) {
188 use_clone = T_CLONE;
189 tsttype = CLONESTR;
190 } else if (strcmp(argv[1], "unshare") == 0) {
191 use_clone = T_UNSHARE;
192 tsttype = UNSHARESTR;
193 }
194
195 tst_resm(TINFO, "Semaphore Namespaces Test : %s", tsttype);
196
197 /* Create 2 containers */
198 ret = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem1, NULL);
199 if (ret < 0) {
200 tst_brkm(TFAIL, NULL, "clone/unshare failed");
201 }
202
203 ret = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_sem2, NULL);
204 if (ret < 0) {
205 tst_brkm(TFAIL, NULL, "clone/unshare failed");
206 }
207 close(p2[1]);
208 read(p2[0], buf, 7);
209
210 if (strcmp(buf, "exists") == 0)
211 if (use_clone == T_NONE)
212 tst_resm(TPASS,
213 "Plain cloned process able to access the semaphore "
214 "created");
215 else
216 tst_resm(TFAIL,
217 "%s : In namespace2 found the semaphore "
218 "created in Namespace1", tsttype);
219 else if (use_clone == T_NONE)
220 tst_resm(TFAIL, "Plain cloned process didn't find semaphore");
221 else
222 tst_resm(TPASS,
223 "%s : In namespace2 unable to access the semaphore "
224 "created in Namespace1", tsttype);
225
226 /* Delete the semaphore */
227 id = semget(MY_KEY, 1, 0);
228 semctl(id, IPC_RMID, 0);
229 tst_exit();
230 }
231