1 /* 2 * 3 * Copyright (C) Bull S.A. 2001 4 * Copyright (c) International Business Machines Corp., 2001 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Test Name: fstat05 23 * 24 * Test Description: 25 * Verify that, 26 * if buffer points outside user's accessible address space fstat(2) 27 * either returns -1 and sets errno to EFAULT 28 * or SIGSEGV is returned instead of EFAULT 29 * 30 * Expected Result: 31 * fstat() should fail with return value -1 and set expected errno. 32 * or 33 * fstat() should fail with SIGSEGV returned. 34 * Both results are considered as acceptable. 35 * 36 * Algorithm: 37 * Setup: 38 * Setup signal handling SIGSEGV included. 39 * Switch to nobody user. 40 * Pause for SIGUSR1 if option specified. 41 * Create temporary directory. 42 * Create a testfile under temporary directory. 43 * 44 * Test: 45 * Buffer points outside user's accessible address space. 46 * Loop if the proper options are given. 47 * Execute system call 48 * Check return code, if system call failed (return=-1) 49 * if errno set == expected errno 50 * Issue sys call fails with expected return value and errno. 51 * Otherwise, 52 * Issue sys call fails with unexpected errno. 53 * Otherwise, 54 * Issue sys call returns unexpected value. 55 * 56 * Sighandler: 57 * if signal == SIGSEGV 58 * Issue sys call fails with expected signal 59 * Otherwise, 60 * Issue sys call fails with unexpected signal. 61 * 62 * Cleanup: 63 * Print errno log and/or timing stats if options given 64 * Close the test file 65 * Delete the temporary directory(s)/file(s) created. 66 * 67 * Usage: <for command-line> 68 * fstat05 [-c n] [-e] [-i n] [-I x] [-p x] [-t] 69 * where, -c n : Run n copies concurrently. 70 * -e : Turn on errno logging. 71 * -i n : Execute test n times. 72 * -I x : Execute test for x seconds. 73 * -P x : Pause for x seconds between iterations. 74 * -t : Turn on syscall timing. 75 * 76 * History 77 * 05/2002 Jacky Malcles 78 * -Ported 79 * 80 * Restrictions: 81 * This test must be run as root. 82 */ 83 84 #include <stdio.h> 85 #include <stdlib.h> 86 #include <unistd.h> 87 #include <fcntl.h> 88 #include <errno.h> 89 #include <string.h> 90 #include <signal.h> 91 #include <sys/types.h> 92 #include <sys/stat.h> 93 #include <pwd.h> 94 95 #include "test.h" 96 #include "safe_macros.h" 97 98 #define TEST_FILE "testfile" 99 100 char nobody_uid[] = "nobody"; 101 struct passwd *ltpuser; 102 103 char *TCID = "fstat05"; 104 int TST_TOTAL = 1; 105 106 int fildes; /* testfile descriptor */ 107 108 void setup(); /* Main setup function for the tests */ 109 void cleanup(); /* cleanup function for the test */ 110 void sighandler(int sig); /* signals handler function for the test */ 111 112 int siglist[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGIOT, 113 SIGBUS, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, 114 SIGTERM, 115 #ifdef SIGSTKFLT 116 SIGSTKFLT, 117 #endif 118 SIGCHLD, SIGCONT, SIGTSTP, SIGTTIN, 119 SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, 120 SIGWINCH, SIGIO, SIGPWR, SIGSYS, 121 #ifdef SIGUNUSED 122 SIGUNUSED 123 #endif 124 }; 125 126 int SIG_SEEN = sizeof(siglist) / sizeof(int); 127 128 #if !defined(UCLINUX) 129 130 int main(int ac, char **av) 131 { 132 struct stat stat_buf; /* stat structure buffer */ 133 struct stat *ptr_str; 134 int lc; 135 136 tst_parse_opts(ac, av, NULL, NULL); 137 138 /* Buffer points outside user's accessible address space. */ 139 ptr_str = &stat_buf; /* if it was for conformance testing */ 140 ptr_str = (void *)sbrk(0) + (4 * getpagesize()); 141 142 /* 143 * Invoke setup function 144 */ 145 setup(); 146 147 for (lc = 0; TEST_LOOPING(lc); lc++) { 148 149 tst_count = 0; 150 151 /* 152 * Call fstat(2). 153 * verify that it fails with -1 return value and 154 * sets appropriate errno. 155 */ 156 TEST(fstat(fildes, ptr_str)); 157 158 /* Check return code from fstat(2) */ 159 if (TEST_RETURN == -1) { 160 if (TEST_ERRNO == EFAULT) 161 tst_resm(TPASS, 162 "fstat failed with EFAULT as expected"); 163 else 164 tst_resm(TFAIL | TTERRNO, 165 "fstat failed unexpectedly"); 166 } else 167 tst_resm(TFAIL, "fstat() returned %ld but we wanted -1", 168 TEST_RETURN); 169 170 } 171 172 /* 173 * Invoke cleanup() to delete the test directory/file(s) created 174 * in the setup(). 175 */ 176 cleanup(); 177 tst_exit(); 178 } 179 180 #else 181 182 int main(void) 183 { 184 tst_brkm(TCONF, NULL, "test is not available on uClinux"); 185 } 186 187 #endif /* if !defined(UCLINUX) */ 188 189 /* 190 * void 191 * setup(void) - performs all ONE TIME setup for this test. 192 * Exit the test program on receipt of unexpected signals. 193 * Create a temporary directory and change directory to it. 194 */ 195 void setup(void) 196 { 197 int i; 198 199 tst_require_root(); 200 201 /* 202 * Capture unexpected signals SIGSEGV included 203 * SIGSEGV being considered as acceptable as returned value 204 */ 205 for (i = 0; i < SIG_SEEN; i++) 206 signal(siglist[i], &sighandler); 207 208 ltpuser = getpwnam(nobody_uid); 209 SAFE_SETUID(NULL, ltpuser->pw_uid); 210 211 tst_tmpdir(); 212 213 /* Create a testfile under temporary directory */ 214 fildes = SAFE_OPEN(cleanup, TEST_FILE, O_RDWR | O_CREAT, 0666); 215 216 TEST_PAUSE; 217 } 218 219 /* 220 * void 221 * cleanup() - Performs all ONE TIME cleanup for this test at 222 * completion or premature exit. 223 * Print test timing stats and errno log if test executed with options. 224 * Remove temporary directory and sub-directories/files under it 225 * created during setup(). 226 * Exit the test program with normal exit code. 227 */ 228 void cleanup(void) 229 { 230 231 SAFE_CLOSE(cleanup, fildes); 232 233 tst_rmdir(); 234 235 } 236 237 /* 238 * sighandler() - handle the signals 239 */ 240 241 void sighandler(int sig) 242 { 243 if (sig == SIGSEGV) 244 tst_resm(TPASS, "fstat failed as expected with SIGSEGV"); 245 else 246 tst_brkm(TBROK, NULL, "Unexpected signal %d received.", sig); 247 cleanup(); 248 tst_exit(); 249 } 250