access05.c revision 354ebb48db8e66a853a58379a4808d5dcd1ceac3
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 * Test Name: access05 22 * 23 * Test Description: 24 * Verify that, 25 * 1. access() fails with -1 return value and sets errno to EACCES 26 * if the permission bits of the file mode do not permit the 27 * requested (Read/Write/Execute) access. 28 * 2. access() fails with -1 return value and sets errno to EINVAL 29 * if the specified access mode argument is invalid. 30 * 3. access() fails with -1 return value and sets errno to EFAULT 31 * if the pathname points outside allocate address space for the 32 * process. 33 * 4. access() fails with -1 return value and sets errno to ENOENT 34 * if the specified file doesn't exist (or pathname is NULL). 35 * 5. access() fails with -1 return value and sets errno to ENAMETOOLONG 36 * if the pathname size is > PATH_MAX characters. 37 * 38 * Expected Result: 39 * access() should fail with return value -1 and set expected errno. 40 * 41 * Algorithm: 42 * Setup: 43 * Setup signal handling. 44 * Create temporary directory. 45 * Pause for SIGUSR1 if option specified. 46 * 47 * Test: 48 * Loop if the proper options are given. 49 * Execute system call 50 * Check return code, if system call failed (return=-1) 51 * if errno set == expected errno 52 * Issue sys call fails with expected return value and errno. 53 * Otherwise, 54 * Issue sys call fails with unexpected errno. 55 * Otherwise, 56 * Issue sys call returns unexpected value. 57 * 58 * Cleanup: 59 * Print errno log and/or timing stats if options given 60 * Delete the temporary directory(s)/file(s) created. 61 * 62 * Usage: <for command-line> 63 * access05 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 64 * where, -c n : Run n copies concurrently. 65 * -e : Turn on errno logging. 66 * -i n : Execute test n times. 67 * -I x : Execute test for x seconds. 68 * -P x : Pause for x seconds between iterations. 69 * -t : Turn on syscall timing. 70 * 71 * HISTORY 72 * 07/2001 Ported by Wayne Boyer 73 * 74 * RESTRICTIONS: 75 * This test should be run by 'non-super-user' only. 76 * 77 */ 78 79#include <stdio.h> 80#include <errno.h> 81#include <unistd.h> 82#include <fcntl.h> 83#include <string.h> 84#include <signal.h> 85#include <sys/types.h> 86#include <sys/stat.h> 87#include <sys/mman.h> 88#include <pwd.h> 89 90#include "test.h" 91#include "usctest.h" 92 93#define INV_OK -1 94#define TEST_FILE1 "test_file1" 95#define TEST_FILE2 "test_file2" 96#define TEST_FILE3 "test_file3" 97#define TEST_FILE4 "test_file4" 98 99#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 100 101void setup1(); /* setup() to test access() for EACCES */ 102void setup2(); /* setup() to test access() for EACCES */ 103void setup3(); /* setup() to test access() for EACCES */ 104void setup4(); /* setup() to test access() for EINVAL */ 105void longpath_setup(); /* setup function to test access() for ENAMETOOLONG */ 106 107#if !defined(UCLINUX) 108char high_address_node[64]; 109#endif 110 111char Longpathname[PATH_MAX + 2]; 112 113struct test_case_t { /* test case structure */ 114 char *pathname; 115 int a_mode; 116 int exp_errno; 117 void (*setupfunc) (void); 118} test_cases[] = { 119 { 120 TEST_FILE1, R_OK, EACCES, setup1}, { 121 TEST_FILE2, W_OK, EACCES, setup2}, { 122 TEST_FILE3, X_OK, EACCES, setup3}, { 123 TEST_FILE4, INV_OK, EINVAL, setup4}, 124#if !defined(UCLINUX) 125 { 126 (char *)-1, R_OK, EFAULT, NULL}, { 127 high_address_node, R_OK, EFAULT, NULL}, 128#endif 129 { 130 "", W_OK, ENOENT, NULL}, { 131Longpathname, R_OK, ENAMETOOLONG, longpath_setup},}; 132 133char *TCID = "access05"; /* Test program identifier. */ 134int TST_TOTAL = sizeof(test_cases) / sizeof(*test_cases); 135int exp_enos[] = { EACCES, EFAULT, EINVAL, ENOENT, ENAMETOOLONG, 0 }; 136 137char nobody_uid[] = "nobody"; 138struct passwd *ltpuser; 139 140void setup(); /* Main setup function of test */ 141void cleanup(); /* cleanup function for the test */ 142 143char *bad_addr = 0; 144 145int main(int ac, char **av) 146{ 147 int lc; 148 char *msg; 149 char *file_name; /* name of the testfile */ 150 int access_mode; /* specified access mode for testfile */ 151 int i; 152 153 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) 154 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 155 156 setup(); 157 158 TEST_EXP_ENOS(exp_enos); 159 160 for (lc = 0; TEST_LOOPING(lc); lc++) { 161 162 Tst_count = 0; 163 164 for (i = 0; i < TST_TOTAL; i++) { 165 file_name = test_cases[i].pathname; 166 access_mode = test_cases[i].a_mode; 167 168#if !defined(UCLINUX) 169 if (file_name == high_address_node) 170 file_name = get_high_address(); 171#endif 172 173 /* 174 * Call access(2) to test different test conditions. 175 * verify that it fails with -1 return value and 176 * sets appropriate errno. 177 */ 178 TEST(access(file_name, access_mode)); 179 180 if (TEST_RETURN != -1) { 181 tst_resm(TFAIL, 182 "access(%s, %#o) succeeded unexpectedly", 183 file_name, access_mode); 184 continue; 185 } 186 187 if (TEST_ERRNO == test_cases[i].exp_errno) 188 tst_resm(TPASS | TTERRNO, 189 "access failed as expected"); 190 else 191 tst_resm(TFAIL | TTERRNO, 192 "access failed unexpectedly; expected: " 193 "%d - %s", 194 test_cases[i].exp_errno, 195 strerror(test_cases[i].exp_errno)); 196 } 197 } 198 199 cleanup(); 200 201 tst_exit(); 202 203} 204 205void setup() 206{ 207 int i; 208 209 tst_sig(NOFORK, DEF_HANDLER, cleanup); 210 211 tst_require_root(NULL); 212 213 ltpuser = getpwnam(nobody_uid); 214 if (ltpuser == NULL) 215 tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); 216 if (setuid(ltpuser->pw_uid) == -1) 217 tst_brkm(TBROK | TERRNO, NULL, "setuid failed"); 218 219 TEST_PAUSE; 220 221#if !defined(UCLINUX) 222 bad_addr = mmap(0, 1, PROT_NONE, 223 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0); 224 if (bad_addr == MAP_FAILED) 225 tst_brkm(TBROK | TERRNO, NULL, "mmap failed"); 226 test_cases[5].pathname = bad_addr; 227#endif 228 229 tst_tmpdir(); 230 231 for (i = 0; i < TST_TOTAL; i++) 232 if (test_cases[i].setupfunc != NULL) 233 test_cases[i].setupfunc(); 234} 235 236void setup_file(const char *file, mode_t perms) 237{ 238 int fd; /* file handle for testfile */ 239 240 if ((fd = open(file, O_RDWR | O_CREAT, FILE_MODE)) == -1) 241 tst_brkm(TBROK | TERRNO, cleanup, 242 "open(%s, O_RDWR|O_CREAT, %#o) failed", 243 file, FILE_MODE); 244 245 if (fchmod(fd, perms) < 0) 246 tst_brkm(TBROK | TERRNO, cleanup, "chmod(%s, %#o) failed", 247 file, perms); 248 if (close(fd) == -1) 249 tst_brkm(TBROK | TERRNO, cleanup, "close(%s) failed", file); 250} 251 252/* 253 * setup1() - Setup function to test access() for return value -1 254 * and errno EACCES when read access denied for specified 255 * testfile. 256 * 257 * Creat/open a testfile and close it. 258 * Deny read access permissions on testfile. 259 * This function returns 0. 260 */ 261void setup1() 262{ 263 setup_file(TEST_FILE1, 0333); 264} 265 266/* 267 * setup2() - Setup function to test access() for return value -1 and 268 * errno EACCES when write access denied on testfile. 269 * 270 * Creat/open a testfile and close it. 271 * Deny write access permissions on testfile. 272 * This function returns 0. 273 */ 274void setup2() 275{ 276 setup_file(TEST_FILE2, 0555); 277} 278 279/* 280 * setup3() - Setup function to test access() for return value -1 and 281 * errno EACCES when execute access denied on testfile. 282 * 283 * Creat/open a testfile and close it. 284 * Deny search access permissions on testfile. 285 * This function returns 0. 286 */ 287void setup3() 288{ 289 setup_file(TEST_FILE3, 0666); 290} 291 292/* 293 * setup4() - Setup function to test access() for return value -1 294 * and errno EINVAL when specified access mode argument is 295 * invalid. 296 * 297 * Creat/open a testfile and close it. 298 * This function returns 0. 299 */ 300void setup4() 301{ 302 setup_file(TEST_FILE4, FILE_MODE); 303} 304 305/* 306 * longpath_setup() - setup to create a node with a name length exceeding 307 * the MAX. length of PATH_MAX. 308 */ 309void longpath_setup() 310{ 311 int i; 312 313 for (i = 0; i <= (PATH_MAX + 1); i++) 314 Longpathname[i] = 'a'; 315} 316 317/* 318 * cleanup() - performs all ONE TIME cleanup for this test at 319 * completion or premature exit. 320 * 321 * Remove the test directory and testfile created in the setup. 322 */ 323void cleanup() 324{ 325 /* 326 * print timing stats if that option was specified. 327 * print errno log if that option was specified. 328 */ 329 TEST_CLEANUP; 330 331 /* 332 * Delete the test directory/file and temporary directory 333 * created in the setup. 334 */ 335 tst_rmdir(); 336 337} 338