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 (at) 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 */ 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 */ 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 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 156 static void setup(void) 157 { 158 tst_require_root(); 159 check_newipc(); 160 } 161 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