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 * shmctl03.c 23 * 24 * DESCRIPTION 25 * shmctl03 - check for EACCES, and EPERM errors 26 * 27 * ALGORITHM 28 * create a shared memory segment with root only read & write permissions 29 * fork a child process 30 * if child 31 * set the ID of the child process to that of "ltpuser1" 32 * call do_child() 33 * loop if that option was specified 34 * call shmctl() using three different invalid cases 35 * check the errno value 36 * issue a PASS message if we get EACCES or 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 shared memory segment 43 * 44 * USAGE: <for command-line> 45 * shmctl03 [-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 "ipcshm.h" 61 #include <sys/types.h> 62 #include <sys/wait.h> 63 #include "safe_macros.h" 64 65 char *TCID = "shmctl03"; 66 int shm_id_1 = -1; 67 68 uid_t ltp_uid; 69 char *ltp_user = "nobody"; 70 71 struct shmid_ds buf; 72 73 struct test_case_t { 74 int *shmid; 75 int cmd; 76 struct shmid_ds *sbuf; 77 int error; 78 } TC[] = { 79 /* EACCES - child has no read permission for segment */ 80 { 81 &shm_id_1, IPC_STAT, &buf, EACCES}, 82 /* EPERM - IPC_SET - child doesn't have permission to change segment */ 83 { 84 &shm_id_1, IPC_SET, &buf, EPERM}, 85 /* EPERM - IPC_RMID - child can not remove the segment */ 86 { 87 &shm_id_1, IPC_RMID, &buf, EPERM},}; 88 89 int TST_TOTAL = ARRAY_SIZE(TC); 90 91 int main(int ac, char **av) 92 { 93 int pid; 94 void do_child(void); 95 96 tst_parse_opts(ac, av, NULL, NULL); 97 98 setup(); /* global setup */ 99 100 if ((pid = FORK_OR_VFORK()) == -1) { 101 tst_brkm(TBROK, cleanup, "could not fork"); 102 } 103 104 if (pid == 0) { /* child */ 105 /* set the user ID of the child to the non root user */ 106 if (setuid(ltp_uid) == -1) { 107 tst_resm(TBROK, "setuid() failed"); 108 exit(1); 109 } 110 111 do_child(); 112 } else { 113 /* wait for the child to return */ 114 SAFE_WAITPID(cleanup, pid, NULL, 0); 115 116 /* if it exists, remove the shared memory resource */ 117 rm_shm(shm_id_1); 118 119 tst_rmdir(); 120 } 121 122 cleanup(); 123 tst_exit(); 124 } 125 126 /* 127 * do_child - make the call as the child process 128 */ 129 void do_child(void) 130 { 131 int i, lc; 132 133 /* The following loop checks looping state if -i option given */ 134 135 for (lc = 0; TEST_LOOPING(lc); lc++) { 136 /* reset tst_count in case we are looping */ 137 tst_count = 0; 138 139 /* loop through the test cases */ 140 for (i = 0; i < TST_TOTAL; i++) { 141 /* 142 * use the TEST() macro to make the call 143 */ 144 145 TEST(shmctl(*(TC[i].shmid), TC[i].cmd, TC[i].sbuf)); 146 147 if (TEST_RETURN != -1) { 148 tst_resm(TFAIL, "call succeeded unexpectedly"); 149 continue; 150 } 151 152 if (TEST_ERRNO == TC[i].error) { 153 tst_resm(TPASS, "expected failure - errno = " 154 "%d : %s", TEST_ERRNO, 155 strerror(TEST_ERRNO)); 156 } else { 157 tst_resm(TFAIL, "call failed with an " 158 "unexpected error - %d : %s", 159 TEST_ERRNO, strerror(TEST_ERRNO)); 160 } 161 } 162 } 163 } 164 165 /* 166 * setup() - performs all the ONE TIME setup for this test. 167 */ 168 void setup(void) 169 { 170 tst_require_root(); 171 172 tst_sig(FORK, DEF_HANDLER, cleanup); 173 174 TEST_PAUSE; 175 176 /* 177 * Create a temporary directory and cd into it. 178 * This helps to ensure that a unique msgkey is created. 179 * See ../lib/libipc.c for more information. 180 */ 181 tst_tmpdir(); 182 183 /* get an IPC resource key */ 184 shmkey = getipckey(); 185 186 /* create a shared memory segment with read and write permissions */ 187 if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | 188 SHM_RW)) == -1) { 189 tst_brkm(TBROK, cleanup, "couldn't create shared memory " 190 "segment in setup()"); 191 } 192 193 /* get the userid for a non root user */ 194 ltp_uid = getuserid(ltp_user); 195 } 196 197 /* 198 * cleanup() - performs all the ONE TIME cleanup for this test at completion 199 * or premature exit. 200 */ 201 void cleanup(void) 202 { 203 204 } 205