xref: /freebsd/lib/libc/tests/secure/fortify_stdlib_test.c (revision 1ace24b30cad59c8ae509d0c690aa55b8df73136)
1 /* @generated by `generate-fortify-tests.lua "stdlib"` */
2 
3 #define	_FORTIFY_SOURCE	2
4 #define	TMPFILE_SIZE	(1024 * 32)
5 
6 #include <sys/param.h>
7 #include <sys/random.h>
8 #include <sys/resource.h>
9 #include <sys/time.h>
10 #include <sys/uio.h>
11 #include <sys/wait.h>
12 #include <dirent.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <limits.h>
16 #include <poll.h>
17 #include <signal.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <strings.h>
22 #include <sysexits.h>
23 #include <unistd.h>
24 #include <wchar.h>
25 #include <atf-c.h>
26 
27 static FILE * __unused
28 new_fp(size_t __len)
29 {
30 	static char fpbuf[LINE_MAX];
31 	FILE *fp;
32 
33 	ATF_REQUIRE(__len <= sizeof(fpbuf));
34 
35 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
36 	fpbuf[sizeof(fpbuf) - 1] = '\0';
37 
38 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
39 	ATF_REQUIRE(fp != NULL);
40 
41 	return (fp);
42 }
43 
44 /*
45  * Create a new symlink to use for readlink(2) style tests, we'll just use a
46  * random target name to have something interesting to look at.
47  */
48 static const char * __unused
49 new_symlink(size_t __len)
50 {
51 	static const char linkname[] = "link";
52 	char target[MAXNAMLEN];
53 	int error;
54 
55 	ATF_REQUIRE(__len <= sizeof(target));
56 
57 	arc4random_buf(target, sizeof(target));
58 
59 	error = unlink(linkname);
60 	ATF_REQUIRE(error == 0 || errno == ENOENT);
61 
62 	error = symlink(target, linkname);
63 	ATF_REQUIRE(error == 0);
64 
65 	return (linkname);
66 }
67 
68 /*
69  * Constructs a tmpfile that we can use for testing read(2) and friends.
70  */
71 static int __unused
72 new_tmpfile(void)
73 {
74 	char buf[1024];
75 	ssize_t rv;
76 	size_t written;
77 	int fd;
78 
79 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
80 	ATF_REQUIRE(fd >= 0);
81 
82 	written = 0;
83 	while (written < TMPFILE_SIZE) {
84 		rv = write(fd, buf, sizeof(buf));
85 		ATF_REQUIRE(rv > 0);
86 
87 		written += rv;
88 	}
89 
90 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
91 	return (fd);
92 }
93 
94 static void
95 disable_coredumps(void)
96 {
97 	struct rlimit rl = { 0 };
98 
99 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
100 		_exit(EX_OSERR);
101 }
102 
103 /*
104  * Replaces stdin with a file that we can actually read from, for tests where
105  * we want a FILE * or fd that we can get data from.
106  */
107 static void __unused
108 replace_stdin(void)
109 {
110 	int fd;
111 
112 	fd = new_tmpfile();
113 
114 	(void)dup2(fd, STDIN_FILENO);
115 	if (fd != STDIN_FILENO)
116 		close(fd);
117 }
118 
119 ATF_TC_WITHOUT_HEAD(arc4random_buf_before_end);
120 ATF_TC_BODY(arc4random_buf_before_end, tc)
121 {
122 #define BUF &__stack.__buf
123 	struct {
124 		uint8_t padding_l;
125 		unsigned char __buf[42];
126 		uint8_t padding_r;
127 	} __stack;
128 	const size_t __bufsz __unused = sizeof(__stack.__buf);
129 	const size_t __len = 42 - 1;
130 	const size_t __idx __unused = __len - 1;
131 
132 	arc4random_buf(__stack.__buf, __len);
133 #undef BUF
134 
135 }
136 
137 ATF_TC_WITHOUT_HEAD(arc4random_buf_end);
138 ATF_TC_BODY(arc4random_buf_end, tc)
139 {
140 #define BUF &__stack.__buf
141 	struct {
142 		uint8_t padding_l;
143 		unsigned char __buf[42];
144 		uint8_t padding_r;
145 	} __stack;
146 	const size_t __bufsz __unused = sizeof(__stack.__buf);
147 	const size_t __len = 42;
148 	const size_t __idx __unused = __len - 1;
149 
150 	arc4random_buf(__stack.__buf, __len);
151 #undef BUF
152 
153 }
154 
155 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_before_end);
156 ATF_TC_BODY(arc4random_buf_heap_before_end, tc)
157 {
158 #define BUF __stack.__buf
159 	struct {
160 		uint8_t padding_l;
161 		unsigned char * __buf;
162 		uint8_t padding_r;
163 	} __stack;
164 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
165 	const size_t __len = 42 - 1;
166 	const size_t __idx __unused = __len - 1;
167 
168 	__stack.__buf = malloc(__bufsz);
169 
170 	arc4random_buf(__stack.__buf, __len);
171 #undef BUF
172 
173 }
174 
175 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_end);
176 ATF_TC_BODY(arc4random_buf_heap_end, tc)
177 {
178 #define BUF __stack.__buf
179 	struct {
180 		uint8_t padding_l;
181 		unsigned char * __buf;
182 		uint8_t padding_r;
183 	} __stack;
184 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
185 	const size_t __len = 42;
186 	const size_t __idx __unused = __len - 1;
187 
188 	__stack.__buf = malloc(__bufsz);
189 
190 	arc4random_buf(__stack.__buf, __len);
191 #undef BUF
192 
193 }
194 
195 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_after_end);
196 ATF_TC_BODY(arc4random_buf_heap_after_end, tc)
197 {
198 #define BUF __stack.__buf
199 	struct {
200 		uint8_t padding_l;
201 		unsigned char * __buf;
202 		uint8_t padding_r;
203 	} __stack;
204 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
205 	const size_t __len = 42 + 1;
206 	const size_t __idx __unused = __len - 1;
207 	pid_t __child;
208 	int __status;
209 
210 	__child = fork();
211 	ATF_REQUIRE(__child >= 0);
212 	if (__child > 0)
213 		goto monitor;
214 
215 	/* Child */
216 	disable_coredumps();
217 	__stack.__buf = malloc(__bufsz);
218 
219 	arc4random_buf(__stack.__buf, __len);
220 	_exit(EX_SOFTWARE);	/* Should have aborted. */
221 
222 monitor:
223 	while (waitpid(__child, &__status, 0) != __child) {
224 		ATF_REQUIRE_EQ(EINTR, errno);
225 	}
226 
227 	if (!WIFSIGNALED(__status)) {
228 		switch (WEXITSTATUS(__status)) {
229 		case EX_SOFTWARE:
230 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
231 			break;
232 		case EX_OSERR:
233 			atf_tc_fail("setrlimit(2) failed");
234 			break;
235 		default:
236 			atf_tc_fail("child exited with status %d",
237 			    WEXITSTATUS(__status));
238 		}
239 	} else {
240 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
241 	}
242 #undef BUF
243 
244 }
245 
246 ATF_TC_WITHOUT_HEAD(realpath_before_end);
247 ATF_TC_BODY(realpath_before_end, tc)
248 {
249 #define BUF &__stack.__buf
250 	struct {
251 		uint8_t padding_l;
252 		unsigned char __buf[PATH_MAX + 1];
253 		uint8_t padding_r;
254 	} __stack;
255 	const size_t __bufsz __unused = sizeof(__stack.__buf);
256 	const size_t __len = PATH_MAX + 1;
257 	const size_t __idx __unused = __len - 1;
258 
259 	realpath(".", __stack.__buf);
260 #undef BUF
261 
262 }
263 
264 ATF_TC_WITHOUT_HEAD(realpath_end);
265 ATF_TC_BODY(realpath_end, tc)
266 {
267 #define BUF &__stack.__buf
268 	struct {
269 		uint8_t padding_l;
270 		unsigned char __buf[PATH_MAX];
271 		uint8_t padding_r;
272 	} __stack;
273 	const size_t __bufsz __unused = sizeof(__stack.__buf);
274 	const size_t __len = PATH_MAX;
275 	const size_t __idx __unused = __len - 1;
276 
277 	realpath(".", __stack.__buf);
278 #undef BUF
279 
280 }
281 
282 ATF_TC_WITHOUT_HEAD(realpath_heap_before_end);
283 ATF_TC_BODY(realpath_heap_before_end, tc)
284 {
285 #define BUF __stack.__buf
286 	struct {
287 		uint8_t padding_l;
288 		unsigned char * __buf;
289 		uint8_t padding_r;
290 	} __stack;
291 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX + 1);
292 	const size_t __len = PATH_MAX + 1;
293 	const size_t __idx __unused = __len - 1;
294 
295 	__stack.__buf = malloc(__bufsz);
296 
297 	realpath(".", __stack.__buf);
298 #undef BUF
299 
300 }
301 
302 ATF_TC_WITHOUT_HEAD(realpath_heap_end);
303 ATF_TC_BODY(realpath_heap_end, tc)
304 {
305 #define BUF __stack.__buf
306 	struct {
307 		uint8_t padding_l;
308 		unsigned char * __buf;
309 		uint8_t padding_r;
310 	} __stack;
311 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX);
312 	const size_t __len = PATH_MAX;
313 	const size_t __idx __unused = __len - 1;
314 
315 	__stack.__buf = malloc(__bufsz);
316 
317 	realpath(".", __stack.__buf);
318 #undef BUF
319 
320 }
321 
322 ATF_TC_WITHOUT_HEAD(realpath_heap_after_end);
323 ATF_TC_BODY(realpath_heap_after_end, tc)
324 {
325 #define BUF __stack.__buf
326 	struct {
327 		uint8_t padding_l;
328 		unsigned char * __buf;
329 		uint8_t padding_r;
330 	} __stack;
331 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX - 1);
332 	const size_t __len = PATH_MAX - 1;
333 	const size_t __idx __unused = __len - 1;
334 	pid_t __child;
335 	int __status;
336 
337 	__child = fork();
338 	ATF_REQUIRE(__child >= 0);
339 	if (__child > 0)
340 		goto monitor;
341 
342 	/* Child */
343 	disable_coredumps();
344 	__stack.__buf = malloc(__bufsz);
345 
346 	realpath(".", __stack.__buf);
347 	_exit(EX_SOFTWARE);	/* Should have aborted. */
348 
349 monitor:
350 	while (waitpid(__child, &__status, 0) != __child) {
351 		ATF_REQUIRE_EQ(EINTR, errno);
352 	}
353 
354 	if (!WIFSIGNALED(__status)) {
355 		switch (WEXITSTATUS(__status)) {
356 		case EX_SOFTWARE:
357 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
358 			break;
359 		case EX_OSERR:
360 			atf_tc_fail("setrlimit(2) failed");
361 			break;
362 		default:
363 			atf_tc_fail("child exited with status %d",
364 			    WEXITSTATUS(__status));
365 		}
366 	} else {
367 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
368 	}
369 #undef BUF
370 
371 }
372 
373 ATF_TP_ADD_TCS(tp)
374 {
375 	ATF_TP_ADD_TC(tp, arc4random_buf_before_end);
376 	ATF_TP_ADD_TC(tp, arc4random_buf_end);
377 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end);
378 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_end);
379 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end);
380 	ATF_TP_ADD_TC(tp, realpath_before_end);
381 	ATF_TP_ADD_TC(tp, realpath_end);
382 	ATF_TP_ADD_TC(tp, realpath_heap_before_end);
383 	ATF_TP_ADD_TC(tp, realpath_heap_end);
384 	ATF_TP_ADD_TC(tp, realpath_heap_after_end);
385 	return (atf_no_error());
386 }
387