semctl04.c revision f6f0bf6255b6027b0b7e38c09413932240c9e3c3
1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20/* 21 * NAME 22 * semctl04.c 23 * 24 * DESCRIPTION 25 * semctl04 - test for EPERM error 26 * 27 * ALGORITHM 28 * create a semaphore set without read or alter permissions 29 * get the user id for "nobody" 30 * fork a child process 31 * if child 32 * set the ID of the child process to that of "nobody" 33 * loop if that option was specified 34 * call semctl() with two different invalid cases 35 * check the errno value 36 * issue a PASS message if we get EPERM 37 * otherwise, the tests fails 38 * issue a FAIL message 39 * call cleanup 40 * if parent 41 * wait for child to exit 42 * remove the semaphore set 43 * 44 * USAGE: <for command-line> 45 * semctl04 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 46 * where, -c n : Run n copies concurrently. 47 * -e : Turn on errno logging. 48 * -i n : Execute test n times. 49 * -I x : Execute test for x seconds. 50 * -P x : Pause for x seconds between iterations. 51 * -t : Turn on syscall timing. 52 * 53 * HISTORY 54 * 03/2001 - Written by Wayne Boyer 55 * 56 * RESTRICTIONS 57 * test must be run as root 58 */ 59 60#include "../lib/ipcsem.h" 61 62#include <pwd.h> 63 64char *TCID = "semctl04"; 65int TST_TOTAL = 2; 66extern int Tst_count; 67 68int exp_enos[] = {EPERM, 0}; /* 0 terminated list of expected errnos */ 69 70int sem_id_1 = -1; 71 72uid_t ltp_uid; 73char *ltp_user = "nobody"; 74 75int TC[] = {IPC_SET, IPC_RMID}; 76 77main(int ac, char **av) 78{ 79 char *msg; /* message returned from parse_opts */ 80 pid_t pid; 81 void do_child(void); 82 83 /* parse standard options */ 84 if ((msg = parse_opts(ac, av, (option_t *)NULL, NULL)) != (char *)NULL){ 85 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); 86 } 87 88 setup(); /* global setup */ 89 90 if ((pid = fork()) == -1) { 91 tst_brkm(TBROK, cleanup, "could not fork"); 92 } 93 94 if (pid == 0) { /* child */ 95 /* set the user ID of the child to the non root user */ 96 if (setuid(ltp_uid) == -1) { 97 tst_resm(TBROK, "setuid() failed"); 98 exit(1); 99 } 100 101 do_child(); 102 103 cleanup(); 104 105 /*NOTREACHED*/ 106 } else { 107 if (waitpid(pid, NULL, 0) == -1) { 108 tst_resm(TBROK, "waitpid() failed"); 109 tst_resm(TINFO, "waitpid() error = %d : %s", errno, 110 strerror(errno)); 111 } 112 113 /* if it exists, remove the semaphore resouce */ 114 rm_sema(sem_id_1); 115 116 /* Remove the temporary directory */ 117 tst_rmdir(); 118 } 119} 120 121/* 122 * do_child() - make the TEST call as the child process 123 */ 124void 125do_child() 126{ 127 int lc; /* loop counter */ 128 int i; 129 union semun arg; 130 struct semid_ds perm; 131 132 /* The following loop checks looping state if -i option given */ 133 134 for (lc = 0; TEST_LOOPING(lc); lc++) { 135 /* reset Tst_count in case we are looping */ 136 Tst_count = 0; 137 138 for (i=0; i<TST_TOTAL; i++) { 139 140 if (TC[i] == IPC_SET) { 141 arg.buf = &perm; 142 memset(&perm, 0, sizeof perm); 143 perm.sem_perm.uid = getuid() + 1; 144 perm.sem_perm.gid = getgid() + 1; 145 perm.sem_perm.mode = 0666; 146 } 147 148 149 TEST(semctl(sem_id_1, 0, TC[i], arg.buf)); 150 151 if (TEST_RETURN != -1) { 152 tst_resm(TFAIL, "call succeeded unexpectedly"); 153 continue; 154 } 155 156 TEST_ERROR_LOG(TEST_ERRNO); 157 158 switch(TEST_ERRNO) { 159 case EPERM: 160 tst_resm(TPASS, "expected failure - errno =" 161 " %d : %s", TEST_ERRNO, 162 strerror(TEST_ERRNO)); 163 break; 164 default: 165 tst_resm(TFAIL, "unexpected error " 166 "- %d : %s", TEST_ERRNO, 167 strerror(TEST_ERRNO)); 168 break; 169 } 170 } 171 } 172} 173 174/* 175 * setup() - performs all the ONE TIME setup for this test. 176 */ 177void 178setup(void) 179{ 180 /* check for root as user id of process */ 181 check_root(); 182 183 /* capture signals */ 184 tst_sig(FORK, DEF_HANDLER, cleanup); 185 186 /* Set up the expected error numbers for -e option */ 187 TEST_EXP_ENOS(exp_enos); 188 189 /* Pause if that option was specified */ 190 TEST_PAUSE; 191 192 /* 193 * Create a temporary directory and cd into it. 194 * This helps to ensure that a unique msgkey is created. 195 * See ../lib/libipc.c for more information. 196 */ 197 tst_tmpdir(); 198 199 /* get an IPC resource key */ 200 semkey = getipckey(); 201 202 /* create a semaphore set without read or alter permissions */ 203 if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL)) == -1) { 204 tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup"); 205 } 206 207 /* get the userid for a non root user */ 208 ltp_uid = getuserid(ltp_user); 209} 210 211/* 212 * cleanup() - performs all the ONE TIME cleanup for this test at completion 213 * or premature exit. 214 */ 215void 216cleanup(void) 217{ 218 /* 219 * print timing stats if that option was specified. 220 * print errno log if that option was specified. 221 */ 222 TEST_CLEANUP; 223 224 /* exit with return code appropriate for results */ 225 tst_exit(); 226} 227 228