• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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