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
main(int ac,char ** av)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
main(void)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 */
setup(void)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 */
cleanup(void)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
sighandler(int sig)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