• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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: shm_comm.c
16  *
17  * Description:
18  * 1. Clones two child processes with CLONE_NEWIPC flag, each child
19  *    allocates System V shared memory segment (shm) with the _identical_
20  *    key and attaches that segment into its address space.
21  * 2. Child1 writes into the shared memory segment.
22  * 3. Child2 writes into the shared memory segment.
23  * 4. Writes to the shared memory segment with the identical key but from
24  *    two different IPC namespaces should not interfere with each other
25  *    and so child1 checks whether its shared segment wasn't changed
26  *    by child2, if it wasn't test passes, otherwise test fails.
27  */
28 
29 #define _GNU_SOURCE
30 #include <sys/ipc.h>
31 #include <sys/shm.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <stdio.h>
35 #include <errno.h>
36 #include "ipcns_helper.h"
37 #include "test.h"
38 #include "safe_macros.h"
39 
40 
41 #define TESTKEY 124426L
42 #define SHMSIZE 50
43 char *TCID	= "shm_comm";
44 int TST_TOTAL	= 1;
45 
cleanup(void)46 static void cleanup(void)
47 {
48 	tst_rmdir();
49 }
50 
setup(void)51 static void setup(void)
52 {
53 	tst_require_root();
54 	check_newipc();
55 	tst_tmpdir();
56 	TST_CHECKPOINT_INIT(tst_rmdir);
57 }
58 
chld1_shm(void * arg)59 int chld1_shm(void *arg)
60 {
61 	int id, rval = 0;
62 	char *shmem;
63 
64 	id = shmget(TESTKEY, SHMSIZE, IPC_CREAT);
65 	if (id == -1) {
66 		perror("shmget");
67 		return 2;
68 	}
69 
70 	if ((shmem = shmat(id, NULL, 0)) == (char *) -1) {
71 		perror("shmat");
72 		shmctl(id, IPC_RMID, NULL);
73 		return 2;
74 	}
75 
76 	*shmem = 'A';
77 
78 	TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
79 
80 	/* if child1 shared segment has changed (by child2) report fail */
81 	if (*shmem != 'A')
82 		rval = 1;
83 
84 	/* tell child2 to continue */
85 	TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
86 
87 	shmdt(shmem);
88 	shmctl(id, IPC_RMID, NULL);
89 	return rval;
90 }
91 
chld2_shm(void * arg)92 int chld2_shm(void *arg)
93 {
94 	int id;
95 	char *shmem;
96 
97 	id = shmget(TESTKEY, SHMSIZE, IPC_CREAT);
98 	if (id == -1) {
99 		perror("shmget");
100 		return 2;
101 	}
102 
103 	if ((shmem = shmat(id, NULL, 0)) == (char *) -1) {
104 		perror("shmat");
105 		shmctl(id, IPC_RMID, NULL);
106 		return 2;
107 	}
108 
109 	/* wait for child1 to write to his segment */
110 	TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
111 
112 	*shmem = 'B';
113 
114 	TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
115 
116 	shmdt(shmem);
117 	shmctl(id, IPC_RMID, NULL);
118 	return 0;
119 }
120 
test(void)121 static void test(void)
122 {
123 	int status, ret = 0;
124 
125 	ret = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld1_shm, NULL);
126 	if (ret == -1)
127 		tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
128 
129 	ret = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, chld2_shm, NULL);
130 	if (ret == -1)
131 		tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
132 
133 
134 	while (wait(&status) > 0) {
135 		if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
136 			ret = 1;
137 		if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
138 			tst_brkm(TBROK | TERRNO, cleanup, "error in child");
139 		if (WIFSIGNALED(status)) {
140 			tst_resm(TFAIL, "child was killed with signal %s",
141 					tst_strsig(WTERMSIG(status)));
142 			return;
143 		}
144 	}
145 
146 	if (ret)
147 		tst_resm(TFAIL, "SysV shm: communication with identical keys"
148 				" between namespaces");
149 	else
150 		tst_resm(TPASS, "SysV shm: communication with identical keys"
151 				" between namespaces");
152 }
153 
main(int argc,char * argv[])154 int main(int argc, char *argv[])
155 {
156 	int lc;
157 
158 	tst_parse_opts(argc, argv, NULL, NULL);
159 
160 	setup();
161 
162 	for (lc = 0; TEST_LOOPING(lc); lc++)
163 		test();
164 
165 	cleanup();
166 	tst_exit();
167 }
168