1 /* 2 * Copyright (c) 2018 Linux Test Project 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * 07/2001 Ported by Wayne Boyer 6 * 21/04/2008 Renaud Lottiaux (Renaud.Lottiaux (at) kerlabs.com) 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 /* 23 * NAME 24 * execve03.c 25 * 26 * DESCRIPTION 27 * Testcase to check execve sets the following errnos correctly: 28 * 1. ENAMETOOLONG 29 * 2. ENOENT 30 * 3. ENOTDIR 31 * 4. EFAULT 32 * 5. EACCES 33 * 6. ENOEXEC 34 * 35 * ALGORITHM 36 * 1. Attempt to execve(2) a file whose name is more than 37 * VFS_MAXNAMLEN fails with ENAMETOOLONG. 38 * 39 * 2. Attempt to execve(2) a file which doesn't exist fails with 40 * ENOENT. 41 * 42 * 3. Attempt to execve(2) a pathname (executabl) comprising of a 43 * directory, which doesn't exist fails with ENOTDIR. 44 * 45 * 4. Attempt to execve(2) a filename not within the address space 46 * of the process fails with EFAULT. 47 * 48 * 5. Attempt to execve(2) a filename that does not have executable 49 * permission - fails with EACCES. 50 * 51 * 6. Attempt to execve(2) a zero length file with executable 52 * permissions - fails with ENOEXEC. 53 * 54 * HISTORY 55 * 07/2001 Ported by Wayne Boyer 56 */ 57 58 #ifndef _GNU_SOURCE 59 #define _GNU_SOURCE 60 #endif 61 #include <sys/types.h> 62 #include <sys/mman.h> 63 #include <sys/stat.h> 64 #include <errno.h> 65 #include <fcntl.h> 66 #include <pwd.h> 67 #include <stdio.h> 68 #include <unistd.h> 69 70 #include "tst_test.h" 71 72 static char nobody_uid[] = "nobody"; 73 static struct passwd *ltpuser; 74 static char long_fname[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz"; 75 static char no_dir[] = "testdir"; 76 static char test_name3[1024]; 77 static char test_name5[1024]; 78 static char test_name6[1024]; 79 80 static struct tcase { 81 char *tname; 82 int error; 83 } tcases[] = { 84 /* the file name is greater than VFS_MAXNAMELEN - ENAMTOOLONG */ 85 {long_fname, ENAMETOOLONG}, 86 /* the filename does not exist - ENOENT */ 87 {no_dir, ENOENT}, 88 /* the path contains a directory name which doesn't exist - ENOTDIR */ 89 {test_name3, ENOTDIR}, 90 /* the filename isn't part of the process address space - EFAULT */ 91 {NULL, EFAULT}, 92 /* the filename does not have execute permission - EACCES */ 93 {test_name5, EACCES}, 94 /* the file is zero length with execute permissions - ENOEXEC */ 95 {test_name6, ENOEXEC} 96 }; 97 98 static void setup(void) 99 { 100 char *cwdname = NULL; 101 unsigned i; 102 int fd; 103 104 umask(0); 105 106 ltpuser = SAFE_GETPWNAM(nobody_uid); 107 108 SAFE_SETGID(ltpuser->pw_gid); 109 110 cwdname = SAFE_GETCWD(cwdname, 0); 111 112 sprintf(test_name5, "%s/fake", cwdname); 113 114 fd = SAFE_CREAT(test_name5, 0444); 115 SAFE_CLOSE(fd); 116 117 sprintf(test_name3, "%s/fake", test_name5); 118 119 /* creat() and close a zero length file with executeable permission */ 120 sprintf(test_name6, "%s/execve03", cwdname); 121 122 fd = SAFE_CREAT(test_name6, 0755); 123 SAFE_CLOSE(fd); 124 125 for (i = 0; i < ARRAY_SIZE(tcases); i++) { 126 if (!tcases[i].tname) 127 tcases[i].tname = tst_get_bad_addr(NULL); 128 } 129 } 130 131 static void verify_execve(unsigned int i) 132 { 133 struct tcase *tc = &tcases[i]; 134 char *argv[2] = {tc->tname, NULL}; 135 136 TEST(execve(tc->tname, argv, NULL)); 137 138 if (TST_RET != -1) { 139 tst_res(TFAIL, "call succeeded unexpectedly"); 140 return; 141 } 142 143 if (TST_ERR == tc->error) { 144 tst_res(TPASS | TTERRNO, "execve failed as expected"); 145 return; 146 } 147 148 tst_res(TFAIL | TTERRNO, "execve failed unexpectedly; expected %s", 149 strerror(tc->error)); 150 } 151 152 static struct tst_test test = { 153 .tcnt = ARRAY_SIZE(tcases), 154 .test = verify_execve, 155 .needs_root = 1, 156 .needs_tmpdir = 1, 157 .child_needs_reinit = 1, 158 .setup = setup, 159 }; 160