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 * execve03.c 23 * 24 * DESCRIPTION 25 * Testcase to check execve sets the following errnos correctly: 26 * 1. ENAMETOOLONG 27 * 2. ENOENT 28 * 3. ENOTDIR 29 * 4. EFAULT 30 * 5. EACCES 31 * 6. ENOEXEC 32 * 33 * ALGORITHM 34 * 1. Attempt to execve(2) a file whose name is more than 35 * VFS_MAXNAMLEN fails with ENAMETOOLONG. 36 * 37 * 2. Attempt to execve(2) a file which doesn't exist fails with 38 * ENOENT. 39 * 40 * 3. Attempt to execve(2) a pathname (executabl) comprising of a 41 * directory, which doesn't exist fails with ENOTDIR. 42 * 43 * 4. Attempt to execve(2) a filename not within the address space 44 * of the process fails with EFAULT. 45 * 46 * 5. Attempt to execve(2) a filename that does not have executable 47 * permission - fails with EACCES. 48 * 49 * 6. Attempt to execve(2) a zero length file with executable 50 * permissions - fails with ENOEXEC. 51 * 52 * USAGE: <for command-line> 53 * execve03 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 54 * where, -c n : Run n copies concurrently. 55 * -e : Turn on errno logging. 56 * -i n : Execute test n times. 57 * -I x : Execute test for x seconds. 58 * -P x : Pause for x seconds between iterations. 59 * -t : Turn on syscall timing. 60 * 61 * HISTORY 62 * 07/2001 Ported by Wayne Boyer 63 * 64 * RESTRICTIONS 65 * test #5 will fail with ETXTBSY not EACCES if the test is run as root 66 */ 67 68 #include <sys/types.h> 69 #include <sys/mman.h> 70 #include <sys/stat.h> 71 #include <errno.h> 72 #include <fcntl.h> 73 #include <pwd.h> 74 #include <stdio.h> 75 76 #include "test.h" 77 #include "safe_macros.h" 78 79 char *TCID = "execve03"; 80 int fileHandle = 0; 81 82 char nobody_uid[] = "nobody"; 83 struct passwd *ltpuser; 84 85 #ifndef UCLINUX 86 void *bad_addr = NULL; 87 #endif 88 89 void setup(void); 90 void cleanup(void); 91 92 char long_file[] = 93 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz"; 94 char no_dir[] = "testdir"; 95 char test_name3[1000]; 96 char test_name5[1000]; 97 char test_name6[1000]; 98 99 struct test_case_t { 100 char *tname; /* the command name to pass to execve() */ 101 int error; 102 } TC[] = { 103 /* the file name is greater than VFS_MAXNAMELEN - ENAMTOOLONG */ 104 { 105 long_file, ENAMETOOLONG}, 106 /* the filename does not exist - ENOENT */ 107 { 108 no_dir, ENOENT}, 109 /* the path contains a directory name which doesn't exist - ENOTDIR */ 110 { 111 test_name3, ENOTDIR}, 112 #if !defined(UCLINUX) 113 /* the filename isn't part of the process address space - EFAULT */ 114 { 115 (char *)-1, EFAULT}, 116 #endif 117 /* the filename does not have execute permission - EACCES */ 118 { 119 test_name5, EACCES}, 120 /* the file is zero length with execute permissions - ENOEXEC */ 121 { 122 test_name6, ENOEXEC} 123 }; 124 125 int TST_TOTAL = ARRAY_SIZE(TC); 126 127 int main(int ac, char **av) 128 { 129 int lc; 130 int i; 131 132 tst_parse_opts(ac, av, NULL, NULL); 133 134 setup(); 135 136 for (lc = 0; TEST_LOOPING(lc); lc++) { 137 138 tst_count = 0; 139 140 for (i = 0; i < TST_TOTAL; i++) { 141 142 TEST(execve(TC[i].tname, av, NULL)); 143 144 if (TEST_RETURN != -1) { 145 tst_resm(TFAIL, "call succeeded unexpectedly"); 146 continue; 147 } 148 149 if (TEST_ERRNO == TC[i].error) 150 tst_resm(TPASS | TTERRNO, 151 "execve failed as expected"); 152 else 153 tst_resm(TFAIL | TTERRNO, 154 "execve failed unexpectedly; expected " 155 "%d - %s", 156 TC[i].error, strerror(TC[i].error)); 157 } 158 } 159 cleanup(); 160 161 tst_exit(); 162 } 163 164 void setup(void) 165 { 166 char *cwdname = NULL; 167 int fd; 168 169 tst_require_root(); 170 171 umask(0); 172 173 tst_sig(NOFORK, DEF_HANDLER, cleanup); 174 175 TEST_PAUSE; 176 177 ltpuser = SAFE_GETPWNAM(NULL, nobody_uid); 178 179 SAFE_SETGID(NULL, ltpuser->pw_gid); 180 181 tst_tmpdir(); 182 183 cwdname = SAFE_GETCWD(cleanup, cwdname, 0); 184 185 sprintf(test_name5, "%s/fake.%d", cwdname, getpid()); 186 187 fileHandle = SAFE_CREAT(cleanup, test_name5, 0444); 188 189 sprintf(test_name3, "%s/fake.%d", test_name5, getpid()); 190 191 /* creat() and close a zero length file with executeable permission */ 192 sprintf(test_name6, "%s/execve03.%d", cwdname, getpid()); 193 194 fd = SAFE_CREAT(cleanup, test_name6, 0755); 195 fd = SAFE_CLOSE(cleanup, fd); 196 #ifndef UCLINUX 197 bad_addr = SAFE_MMAP(cleanup, NULL, 1, PROT_NONE, 198 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0); 199 TC[3].tname = bad_addr; 200 #endif 201 } 202 203 void cleanup(void) 204 { 205 #ifndef UCLINUX 206 SAFE_MUNMAP(NULL, bad_addr, 1); 207 #endif 208 SAFE_CLOSE(NULL, fileHandle); 209 210 tst_rmdir(); 211 212 } 213