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 * shmat02.c 23 * 24 * DESCRIPTION 25 * shmat02 - check for EINVAL and EACCES errors 26 * 27 * ALGORITHM 28 * loop if that option was specified 29 * call shmat() using three invalid test cases 30 * check the errno value 31 * issue a PASS message if we get EINVAL or EACCES 32 * otherwise, the tests fails 33 * issue a FAIL message 34 * call cleanup 35 * 36 * USAGE: <for command-line> 37 * shmat02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 38 * where, -c n : Run n copies concurrently. 39 * -e : Turn on errno logging. 40 * -i n : Execute test n times. 41 * -I x : Execute test for x seconds. 42 * -P x : Pause for x seconds between iterations. 43 * -t : Turn on syscall timing. 44 * 45 * HISTORY 46 * 03/2001 - Written by Wayne Boyer 47 * 48 * 27/02/2008 Renaud Lottiaux (Renaud.Lottiaux (at) kerlabs.com) 49 * - Fix concurrency issue. The second key used for this test could 50 * conflict with the key from another task. 51 * 52 * RESTRICTIONS 53 * Must be ran as non-root 54 */ 55 56 #include "ipcshm.h" 57 #include <pwd.h> 58 #include "shmat_common.h" 59 60 char *TCID = "shmat02"; 61 char nobody_uid[] = "nobody"; 62 struct passwd *ltpuser; 63 64 int shm_id_1 = -1; 65 int shm_id_2 = -1; 66 int shm_id_3 = -1; 67 68 void *base_addr; /* By probing this address first, we can make 69 * non-aligned addresses from it for different 70 * architectures without explicitly code it. 71 */ 72 73 void *addr; /* for result of shmat-call */ 74 75 struct test_case_t { 76 int *shmid; 77 int offset; 78 int error; 79 }; 80 81 int TST_TOTAL = 3; 82 83 static void setup_tc(int i, struct test_case_t *tc) 84 { 85 86 struct test_case_t TC[] = { 87 /* EINVAL - the shared memory ID is not valid */ 88 {&shm_id_1, 0, EINVAL}, 89 /* EINVAL - the address is not page aligned and SHM_RND is not given */ 90 {&shm_id_2, SHMLBA - 1, EINVAL}, 91 /* EACCES - the shared memory resource has no read/write permission */ 92 {&shm_id_3, 0, EACCES} 93 }; 94 95 if (i > TST_TOTAL || i < 0) 96 return; 97 98 *tc = TC[i]; 99 } 100 101 int main(int ac, char **av) 102 { 103 int lc; 104 int i; 105 struct test_case_t *tc; 106 107 tc = NULL; 108 109 tst_parse_opts(ac, av, NULL, NULL); 110 111 tc = malloc(sizeof(struct test_case_t)); 112 if (tc == NULL) 113 tst_brkm(TBROK | TERRNO, cleanup, "malloc failed"); 114 115 setup(); 116 117 for (lc = 0; TEST_LOOPING(lc); lc++) { 118 tst_count = 0; 119 120 for (i = 0; i < TST_TOTAL; i++) { 121 122 setup_tc(i, tc); 123 124 base_addr = probe_free_addr(); 125 errno = 0; 126 addr = shmat(*(tc->shmid), base_addr + tc->offset, 0); 127 128 if (addr != (void *)-1) { 129 tst_resm(TFAIL, "call succeeded unexpectedly"); 130 continue; 131 } 132 133 if (errno == tc->error) 134 tst_resm(TPASS | TERRNO, 135 "shmat failed as expected"); 136 else 137 tst_resm(TFAIL, 138 "shmat failed unexpectedly; expected: " 139 "%d - %s", tc->error, 140 strerror(tc->error)); 141 } 142 } 143 144 cleanup(); 145 146 tst_exit(); 147 } 148 149 void setup(void) 150 { 151 key_t shmkey2; 152 153 tst_require_root(); 154 ltpuser = getpwnam(nobody_uid); 155 if (ltpuser == NULL) 156 tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); 157 if (setuid(ltpuser->pw_uid) == -1) 158 tst_brkm(TBROK | TERRNO, NULL, "setuid failed"); 159 160 tst_sig(NOFORK, DEF_HANDLER, cleanup); 161 162 TEST_PAUSE; 163 164 tst_tmpdir(); 165 166 shmkey = getipckey(); 167 168 shm_id_2 = shmget(shmkey, INT_SIZE, SHM_RW | IPC_CREAT | IPC_EXCL); 169 if (shm_id_2 == -1) 170 tst_brkm(TBROK | TERRNO, cleanup, "shmget #1 failed"); 171 172 /* Get an new IPC resource key. */ 173 shmkey2 = getipckey(); 174 175 /* create a shared memory resource without read and write permissions */ 176 shm_id_3 = shmget(shmkey2, INT_SIZE, IPC_CREAT | IPC_EXCL); 177 if (shm_id_3 == -1) 178 tst_brkm(TBROK | TERRNO, cleanup, "shmget #2 failed"); 179 } 180 181 void cleanup(void) 182 { 183 /* if they exist, remove the shared memory resources */ 184 rm_shm(shm_id_2); 185 rm_shm(shm_id_3); 186 187 tst_rmdir(); 188 189 } 190