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 Shared Memory isoloation in 2 containers.
20 * It tries to create/access a Shared Memory 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 Shared Memory segment with key 124426L
26 * In Cont2, try to access the MQ created in Cont1.
27 * PASS :
28 * 		If flag = None and the shmem seg is accessible in Cont2.
29 *		If flag = unshare/clone and the shmem seg is not accessible in Cont2.
30 * 		If shmem seg is not accessible in Cont2,
31 *		creates new shmem with same key to double check isloation in IPCNS.
32 *
33 * FAIL :
34 * 		If flag = none and the shmem seg is not accessible.
35 * 		If flag = unshare/clone and shmem seg is accessible in Cont2.
36 *		If the new shmem seg 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/shm.h>
46 #include <libclone.h>
47 #include "test.h"
48 #include "safe_macros.h"
49 #include "ipcns_helper.h"
50 
51 #define TESTKEY    124426L
52 #define UNSHARESTR "unshare"
53 #define CLONESTR   "clone"
54 #define NONESTR    "none"
55 
56 char *TCID = "shmem_2nstest";
57 int TST_TOTAL = 1;
58 int p2[2];
59 int p1[2];
60 
61 /*
62  * check_shmem1() does not read -- it writes to check_shmem2() when it's done.
63  */
check_shmem1(void * vtest)64 int check_shmem1(void *vtest)
65 {
66 	int id1;
67 
68 	(void) vtest;
69 
70 	close(p1[0]);
71 
72 	/* first create the key */
73 	id1 = shmget(TESTKEY, 100, IPC_CREAT);
74 	if (id1 == -1)
75 		tst_brkm(TFAIL | TERRNO, NULL, "shmget failed");
76 
77 	tst_resm(TINFO, "Cont1: Able to create shared mem segment");
78 	write(p1[1], "done", 5);
79 	tst_exit();
80 }
81 
82 /*
83  * check_shmem2() reads from check_shmem1() and writes to main() when it's done.
84  */
check_shmem2(void * vtest)85 int check_shmem2(void *vtest)
86 {
87 	char buf[3];
88 	int id2;
89 
90 	(void) vtest;
91 
92 	close(p1[1]);
93 	close(p2[0]);
94 
95 	read(p1[0], buf, 3);
96 	/* Trying to access shmem, if not existing create new shmem */
97 	id2 = shmget(TESTKEY, 100, 0);
98 	if (id2 == -1) {
99 		id2 = shmget(TESTKEY, 100, IPC_CREAT);
100 		if (id2 == -1)
101 			tst_resm(TFAIL | TERRNO, "shmget failed");
102 		else
103 			tst_resm(TINFO,
104 				 "Cont2: Able to allocate shmem seg with "
105 				 "the same key");
106 		write(p2[1], "notfnd", 7);
107 	} else
108 		write(p2[1], "exists", 7);
109 
110 	tst_exit();
111 }
112 
setup(void)113 static void setup(void)
114 {
115 	tst_require_root();
116 	check_newipc();
117 }
118 
main(int argc,char * argv[])119 int main(int argc, char *argv[])
120 {
121 	int ret, use_clone = T_NONE;
122 	char *tsttype = NONESTR;
123 	char buf[7];
124 	int id;
125 
126 	setup();
127 
128 	if (argc != 2) {
129 		tst_resm(TINFO, "Usage: %s <clone| unshare| none>", argv[0]);
130 		tst_resm(TINFO, " where clone, unshare, or fork specifies"
131 			 " unshare method.");
132 		tst_exit();
133 	}
134 
135 	/* Using PIPE's to sync between containers and Parent */
136 	SAFE_PIPE(NULL, p1);
137 	SAFE_PIPE(NULL, p2);
138 
139 	if (strcmp(argv[1], "clone") == 0) {
140 		use_clone = T_CLONE;
141 		tsttype = CLONESTR;
142 	} else if (strcmp(argv[1], "unshare") == 0) {
143 		use_clone = T_UNSHARE;
144 		tsttype = UNSHARESTR;
145 	}
146 
147 	tst_resm(TINFO, "Shared Memory namespace test : %s", tsttype);
148 
149 	/* Create 2 containers */
150 	ret =
151 	    do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem1, NULL);
152 	if (ret < 0)
153 		tst_brkm(TFAIL, NULL, "clone/unshare failed");
154 
155 	ret =
156 	    do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_shmem2, NULL);
157 	if (ret < 0)
158 		tst_brkm(TFAIL, NULL, "clone/unshare failed");
159 
160 	close(p2[1]);
161 	read(p2[0], buf, 7);
162 
163 	if (strcmp(buf, "exists") == 0) {
164 		if (use_clone == T_NONE)
165 			tst_resm(TPASS,
166 				 "Plain cloned process able to access shmem "
167 				 "segment created");
168 		else
169 			tst_resm(TFAIL,
170 				 "%s : In namespace2 found the shmem segment "
171 				 "created in Namespace1", tsttype);
172 	} else {
173 		if (use_clone == T_NONE)
174 			tst_resm(TFAIL,
175 				 "Plain cloned process didn't find shmem seg");
176 		else
177 			tst_resm(TPASS,
178 				 "%s : In namespace2 unable to access the shmem seg "
179 				 "created in Namespace1", tsttype);
180 	}
181 	/* destroy the key */
182 
183 	id = shmget(TESTKEY, 100, 0);
184 	shmctl(id, IPC_RMID, NULL);
185 
186 	tst_exit();
187 }
188