1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 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 Foundation, 17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * Test Description: 21 * Verify that, 22 * 1) lstat(2) returns -1 and sets errno to EACCES if search permission is 23 * denied on a component of the path prefix. 24 * 2) lstat(2) returns -1 and sets errno to ENOENT if the specified file 25 * does not exists or empty string. 26 * 3) lstat(2) returns -1 and sets errno to EFAULT if pathname points 27 * outside user's accessible address space. 28 * 4) lstat(2) returns -1 and sets errno to ENAMETOOLONG if the pathname 29 * component is too long. 30 * 5) lstat(2) returns -1 and sets errno to ENOTDIR if the directory 31 * component in pathname is not a directory. 32 * 6) lstat(2) returns -1 and sets errno to ELOOP if the pathname has too 33 * many symbolic links encountered while traversing. 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <fcntl.h> 40 #include <errno.h> 41 #include <string.h> 42 #include <signal.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <sys/mman.h> 46 #include <pwd.h> 47 48 #include "test.h" 49 #include "safe_macros.h" 50 51 #define MODE_RWX S_IRWXU | S_IRWXG | S_IRWXO 52 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 53 #define TEST_DIR "test_dir" 54 #define TEST_EACCES TEST_DIR"/test_eacces" 55 #define TEST_ENOENT "" 56 #define TEST_ENOTDIR "test_file/test_enotdir" 57 #define TEST_ELOOP "/test_eloop" 58 59 static char longpathname[PATH_MAX + 2]; 60 static char elooppathname[sizeof(TEST_ELOOP) * 43] = "."; 61 62 #if !defined(UCLINUX) 63 static void bad_addr_setup(int); 64 static void high_address_setup(int); 65 #endif 66 67 static struct test_case_t { 68 char *pathname; 69 int exp_errno; 70 void (*setup) (); 71 } test_cases[] = { 72 {TEST_EACCES, EACCES, NULL}, 73 {TEST_ENOENT, ENOENT, NULL}, 74 #if !defined(UCLINUX) 75 {NULL, EFAULT, bad_addr_setup}, 76 {NULL, EFAULT, high_address_setup}, 77 #endif 78 {longpathname, ENAMETOOLONG, NULL}, 79 {TEST_ENOTDIR, ENOTDIR, NULL}, 80 {elooppathname, ELOOP, NULL}, 81 }; 82 83 char *TCID = "lstat02"; 84 int TST_TOTAL = ARRAY_SIZE(test_cases); 85 86 static void setup(void); 87 static void lstat_verify(int); 88 static void cleanup(void); 89 90 int main(int ac, char **av) 91 { 92 int lc; 93 int i; 94 95 tst_parse_opts(ac, av, NULL, NULL); 96 97 setup(); 98 99 for (lc = 0; TEST_LOOPING(lc); lc++) { 100 tst_count = 0; 101 for (i = 0; i < TST_TOTAL; i++) 102 lstat_verify(i); 103 } 104 105 cleanup(); 106 tst_exit(); 107 } 108 109 static void setup(void) 110 { 111 int i; 112 struct passwd *ltpuser; 113 114 tst_require_root(); 115 116 tst_sig(NOFORK, DEF_HANDLER, cleanup); 117 118 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 119 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 120 121 TEST_PAUSE; 122 123 tst_tmpdir(); 124 125 SAFE_MKDIR(cleanup, TEST_DIR, MODE_RWX); 126 SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); 127 SAFE_CHMOD(cleanup, TEST_DIR, FILE_MODE); 128 129 SAFE_TOUCH(cleanup, "test_file", MODE_RWX, NULL); 130 131 memset(longpathname, 'a', PATH_MAX+1); 132 133 SAFE_MKDIR(cleanup, "test_eloop", MODE_RWX); 134 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop"); 135 /* 136 * NOTE: the ELOOP test is written based on that the consecutive 137 * symlinks limits in kernel is hardwired to 40. 138 */ 139 for (i = 0; i < 43; i++) 140 strcat(elooppathname, TEST_ELOOP); 141 } 142 143 #if !defined(UCLINUX) 144 static void bad_addr_setup(int i) 145 { 146 test_cases[i].pathname = SAFE_MMAP(cleanup, 0, 1, PROT_NONE, 147 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 148 } 149 150 static void high_address_setup(int i) 151 { 152 test_cases[i].pathname = (char *)get_high_address(); 153 } 154 #endif 155 156 static void lstat_verify(int i) 157 { 158 struct stat stat_buf; 159 160 if (test_cases[i].setup != NULL) 161 test_cases[i].setup(i); 162 163 TEST(lstat(test_cases[i].pathname, &stat_buf)); 164 165 if (TEST_RETURN != -1) { 166 tst_resm(TFAIL, "lstat() returned %ld, expected -1, errno=%d", 167 TEST_RETURN, test_cases[i].exp_errno); 168 return; 169 } 170 171 if (TEST_ERRNO == test_cases[i].exp_errno) { 172 tst_resm(TPASS | TTERRNO, "lstat() failed as expected"); 173 } else { 174 tst_resm(TFAIL | TTERRNO, 175 "lstat() failed unexpectedly; expected: %d - %s", 176 test_cases[i].exp_errno, 177 strerror(test_cases[i].exp_errno)); 178 } 179 } 180 181 static void cleanup(void) 182 { 183 if (seteuid(0)) 184 tst_resm(TINFO | TERRNO, "Failet to seteuid(0) before cleanup"); 185 186 tst_rmdir(); 187 } 188