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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "ipcsem.h" 61 62 #include <pwd.h> 63 #include <sys/wait.h> 64 65 char *TCID = "semctl04"; 66 int TST_TOTAL = 2; 67 68 int sem_id_1 = -1; 69 70 uid_t ltp_uid; 71 char *ltp_user = "nobody"; 72 73 int TC[] = { IPC_SET, IPC_RMID }; 74 75 int main(int ac, char **av) 76 { 77 pid_t pid; 78 void do_child(void); 79 80 tst_parse_opts(ac, av, NULL, NULL); 81 82 setup(); /* global setup */ 83 84 if ((pid = FORK_OR_VFORK()) == -1) { 85 tst_brkm(TBROK, cleanup, "could not fork"); 86 } 87 88 if (pid == 0) { /* child */ 89 /* set the user ID of the child to the non root user */ 90 if (setuid(ltp_uid) == -1) { 91 tst_resm(TBROK, "setuid() failed"); 92 exit(1); 93 } 94 95 do_child(); 96 97 } else { 98 if (waitpid(pid, NULL, 0) == -1) { 99 tst_resm(TBROK, "waitpid() failed"); 100 tst_resm(TINFO, "waitpid() error = %d : %s", errno, 101 strerror(errno)); 102 } 103 104 /* if it exists, remove the semaphore resouce */ 105 rm_sema(sem_id_1); 106 107 tst_rmdir(); 108 } 109 cleanup(); 110 111 tst_exit(); 112 } 113 114 /* 115 * do_child() - make the TEST call as the child process 116 */ 117 void do_child(void) 118 { 119 int lc; 120 int i; 121 union semun arg; 122 struct semid_ds perm; 123 124 /* The following loop checks looping state if -i option given */ 125 126 for (lc = 0; TEST_LOOPING(lc); lc++) { 127 /* reset tst_count in case we are looping */ 128 tst_count = 0; 129 130 for (i = 0; i < TST_TOTAL; i++) { 131 132 if (TC[i] == IPC_SET) { 133 arg.buf = &perm; 134 memset(&perm, 0, sizeof perm); 135 perm.sem_perm.uid = getuid() + 1; 136 perm.sem_perm.gid = getgid() + 1; 137 perm.sem_perm.mode = 0666; 138 } 139 140 TEST(semctl(sem_id_1, 0, TC[i], arg)); 141 142 if (TEST_RETURN != -1) { 143 tst_resm(TFAIL, "call succeeded unexpectedly"); 144 continue; 145 } 146 147 switch (TEST_ERRNO) { 148 case EPERM: 149 tst_resm(TPASS, "expected failure - errno =" 150 " %d : %s", TEST_ERRNO, 151 strerror(TEST_ERRNO)); 152 break; 153 default: 154 tst_resm(TFAIL, "unexpected error " 155 "- %d : %s", TEST_ERRNO, 156 strerror(TEST_ERRNO)); 157 break; 158 } 159 } 160 } 161 } 162 163 /* 164 * setup() - performs all the ONE TIME setup for this test. 165 */ 166 void setup(void) 167 { 168 tst_require_root(); 169 170 tst_sig(FORK, DEF_HANDLER, cleanup); 171 172 TEST_PAUSE; 173 174 /* 175 * Create a temporary directory and cd into it. 176 * This helps to ensure that a unique msgkey is created. 177 * See ../lib/libipc.c for more information. 178 */ 179 tst_tmpdir(); 180 181 /* get an IPC resource key */ 182 semkey = getipckey(); 183 184 /* create a semaphore set without read or alter permissions */ 185 if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL)) == -1) { 186 tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup"); 187 } 188 189 /* get the userid for a non root user */ 190 ltp_uid = getuserid(ltp_user); 191 } 192 193 /* 194 * cleanup() - performs all the ONE TIME cleanup for this test at completion 195 * or premature exit. 196 */ 197 void cleanup(void) 198 { 199 200 } 201