1 /* 2 * Copyright (c) 2013 Wanlong Gao <gaowanlong (at) cn.fujitsu.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /* 20 * DESCRIPTION 21 * Check for the following errors: 22 * 1. EEXIST 23 * 2. EISDIR 24 * 3. ENOTDIR 25 * 4. ENAMETOOLONG 26 * 5. EACCES 27 * 6. EFAULT 28 * 29 * ALGORITHM 30 * 1. Open a file with O_CREAT and O_EXCL, when the file already 31 * exists. Check the errno for EEXIST 32 * 33 * 2. Pass a directory as the pathname and request a write access, 34 * check for errno for EISDIR 35 * 36 * 3. Specify O_DIRECTORY as a parameter to open and pass a file as the 37 * pathname, check errno for ENOTDIR 38 * 39 * 4. Attempt to open() a filename which is more than VFS_MAXNAMLEN, and 40 * check for errno to be ENAMETOOLONG. 41 * 42 * 5. Attempt to open a test executable in WRONLY mode, 43 * open(2) should fail with EACCES. 44 * 45 * 6. Attempt to pass an invalid pathname with an address pointing outside 46 * the address space of the process, as the argument to open(), and 47 * expect to get EFAULT. 48 */ 49 50 #define _GNU_SOURCE /* for O_DIRECTORY */ 51 #include <sys/types.h> 52 #include <sys/stat.h> 53 #include <stdio.h> 54 #include <errno.h> 55 #include <sys/mman.h> 56 #include <fcntl.h> 57 #include <signal.h> 58 #include <pwd.h> 59 #include "test.h" 60 #include "safe_macros.h" 61 62 static void setup(void); 63 static void cleanup(void); 64 65 char *TCID = "open08"; 66 67 static char nobody_uid[] = "nobody"; 68 static struct passwd *ltpuser; 69 70 static char *bad_addr; 71 72 static char filename[40] = ""; 73 static char fname[] = "/bin/cat"; 74 static char bad_file[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz"; 75 76 static struct test_case_t { 77 char *fname; 78 int flags; 79 int error; 80 } TC[] = { 81 {filename, O_CREAT | O_EXCL, EEXIST}, 82 {"/tmp", O_RDWR, EISDIR}, 83 {filename, O_DIRECTORY, ENOTDIR}, 84 {bad_file, O_RDWR, ENAMETOOLONG}, 85 {fname, O_WRONLY, EACCES}, 86 #if !defined(UCLINUX) 87 {(char *)-1, O_CREAT, EFAULT} 88 #endif 89 }; 90 91 int TST_TOTAL = sizeof(TC) / sizeof(TC[0]); 92 93 int main(int ac, char **av) 94 { 95 int lc; 96 int i; 97 98 tst_parse_opts(ac, av, NULL, NULL); 99 100 setup(); 101 102 for (lc = 0; TEST_LOOPING(lc); lc++) { 103 tst_count = 0; 104 105 for (i = 0; i < TST_TOTAL; i++) { 106 TEST(open(TC[i].fname, TC[i].flags, 107 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); 108 109 if (TEST_RETURN != -1) { 110 tst_resm(TFAIL, "call succeeded unexpectedly"); 111 continue; 112 } 113 114 if (TEST_ERRNO == TC[i].error) { 115 tst_resm(TPASS, "expected failure - " 116 "errno = %d : %s", TEST_ERRNO, 117 strerror(TEST_ERRNO)); 118 } else { 119 tst_resm(TFAIL, "unexpected error - %d : %s - " 120 "expected %d", TEST_ERRNO, 121 strerror(TEST_ERRNO), TC[i].error); 122 } 123 } 124 } 125 126 cleanup(); 127 tst_exit(); 128 } 129 130 static void setup(void) 131 { 132 int fildes; 133 134 tst_require_root(); 135 136 tst_sig(NOFORK, DEF_HANDLER, cleanup); 137 138 umask(0); 139 140 TEST_PAUSE; 141 142 /* Switch to nobody user for correct error code collection */ 143 ltpuser = getpwnam(nobody_uid); 144 SAFE_SETGID(NULL, ltpuser->pw_gid); 145 SAFE_SETUID(NULL, ltpuser->pw_uid); 146 147 tst_tmpdir(); 148 149 sprintf(filename, "open3.%d", getpid()); 150 151 fildes = SAFE_CREAT(cleanup, filename, 0600); 152 153 close(fildes); 154 155 #if !defined(UCLINUX) 156 bad_addr = mmap(0, 1, PROT_NONE, 157 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0); 158 if (bad_addr == MAP_FAILED) 159 tst_brkm(TBROK, cleanup, "mmap failed"); 160 161 TC[5].fname = bad_addr; 162 #endif 163 } 164 165 static void cleanup(void) 166 { 167 tst_rmdir(); 168 } 169