xref: /freebsd/lib/libc/tests/secure/fortify_stdlib_test.c (revision 873420ca1e6e8a2459684f5b5d3e557a8ef75928)
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/jail.h>
8 #include <sys/random.h>
9 #include <sys/resource.h>
10 #include <sys/select.h>
11 #include <sys/socket.h>
12 #include <sys/time.h>
13 #include <sys/uio.h>
14 #include <sys/wait.h>
15 #include <dirent.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <limits.h>
19 #include <poll.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <sysexits.h>
26 #include <unistd.h>
27 #include <wchar.h>
28 #include <atf-c.h>
29 
30 static FILE * __unused
31 new_fp(size_t __len)
32 {
33 	static char fpbuf[LINE_MAX];
34 	FILE *fp;
35 
36 	ATF_REQUIRE(__len <= sizeof(fpbuf));
37 
38 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
39 	fpbuf[sizeof(fpbuf) - 1] = '\0';
40 
41 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
42 	ATF_REQUIRE(fp != NULL);
43 
44 	return (fp);
45 }
46 
47 /*
48  * Create a new symlink to use for readlink(2) style tests, we'll just use a
49  * random target name to have something interesting to look at.
50  */
51 static const char * __unused
52 new_symlink(size_t __len)
53 {
54 	static const char linkname[] = "link";
55 	char target[MAXNAMLEN];
56 	int error;
57 
58 	ATF_REQUIRE(__len <= sizeof(target));
59 
60 	arc4random_buf(target, sizeof(target));
61 
62 	error = unlink(linkname);
63 	ATF_REQUIRE(error == 0 || errno == ENOENT);
64 
65 	error = symlink(target, linkname);
66 	ATF_REQUIRE(error == 0);
67 
68 	return (linkname);
69 }
70 
71 /*
72  * For our purposes, first descriptor will be the reader; we'll send both
73  * raw data and a control message over it so that the result can be used for
74  * any of our recv*() tests.
75  */
76 static void __unused
77 new_socket(int sock[2])
78 {
79 	unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
80 	static char sockbuf[256];
81 	ssize_t rv;
82 	size_t total = 0;
83 	struct msghdr hdr = { 0 };
84 	struct cmsghdr *cmsg;
85 	int error, fd;
86 
87 	error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
88 	ATF_REQUIRE(error == 0);
89 
90 	while (total != sizeof(sockbuf)) {
91 		rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
92 
93 		ATF_REQUIRE_MSG(rv > 0,
94 		    "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
95 		    rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
96 		ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
97 		    "%zd exceeds total %zu", rv, sizeof(sockbuf));
98 		total += rv;
99 	}
100 
101 	hdr.msg_control = ctrl;
102 	hdr.msg_controllen = sizeof(ctrl);
103 
104 	cmsg = CMSG_FIRSTHDR(&hdr);
105 	cmsg->cmsg_level = SOL_SOCKET;
106 	cmsg->cmsg_type = SCM_RIGHTS;
107 	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
108 	fd = STDIN_FILENO;
109 	memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
110 
111 	error = sendmsg(sock[1], &hdr, 0);
112 	ATF_REQUIRE(error != -1);
113 }
114 
115 /*
116  * Constructs a tmpfile that we can use for testing read(2) and friends.
117  */
118 static int __unused
119 new_tmpfile(void)
120 {
121 	char buf[1024];
122 	ssize_t rv;
123 	size_t written;
124 	int fd;
125 
126 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
127 	ATF_REQUIRE(fd >= 0);
128 
129 	written = 0;
130 	while (written < TMPFILE_SIZE) {
131 		rv = write(fd, buf, sizeof(buf));
132 		ATF_REQUIRE(rv > 0);
133 
134 		written += rv;
135 	}
136 
137 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
138 	return (fd);
139 }
140 
141 static void
142 disable_coredumps(void)
143 {
144 	struct rlimit rl = { 0 };
145 
146 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
147 		_exit(EX_OSERR);
148 }
149 
150 /*
151  * Replaces stdin with a file that we can actually read from, for tests where
152  * we want a FILE * or fd that we can get data from.
153  */
154 static void __unused
155 replace_stdin(void)
156 {
157 	int fd;
158 
159 	fd = new_tmpfile();
160 
161 	(void)dup2(fd, STDIN_FILENO);
162 	if (fd != STDIN_FILENO)
163 		close(fd);
164 }
165 
166 ATF_TC(arc4random_buf_before_end);
167 ATF_TC_HEAD(arc4random_buf_before_end, tc)
168 {
169 }
170 ATF_TC_BODY(arc4random_buf_before_end, tc)
171 {
172 #define BUF &__stack.__buf
173 	struct {
174 		uint8_t padding_l;
175 		unsigned char __buf[42];
176 		uint8_t padding_r;
177 	} __stack;
178 	const size_t __bufsz __unused = sizeof(__stack.__buf);
179 	const size_t __len = 42 - 1;
180 	const size_t __idx __unused = __len - 1;
181 
182 	arc4random_buf(__stack.__buf, __len);
183 #undef BUF
184 
185 }
186 
187 ATF_TC(arc4random_buf_end);
188 ATF_TC_HEAD(arc4random_buf_end, tc)
189 {
190 }
191 ATF_TC_BODY(arc4random_buf_end, tc)
192 {
193 #define BUF &__stack.__buf
194 	struct {
195 		uint8_t padding_l;
196 		unsigned char __buf[42];
197 		uint8_t padding_r;
198 	} __stack;
199 	const size_t __bufsz __unused = sizeof(__stack.__buf);
200 	const size_t __len = 42;
201 	const size_t __idx __unused = __len - 1;
202 
203 	arc4random_buf(__stack.__buf, __len);
204 #undef BUF
205 
206 }
207 
208 ATF_TC(arc4random_buf_heap_before_end);
209 ATF_TC_HEAD(arc4random_buf_heap_before_end, tc)
210 {
211 }
212 ATF_TC_BODY(arc4random_buf_heap_before_end, tc)
213 {
214 #define BUF __stack.__buf
215 	struct {
216 		uint8_t padding_l;
217 		unsigned char * __buf;
218 		uint8_t padding_r;
219 	} __stack;
220 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
221 	const size_t __len = 42 - 1;
222 	const size_t __idx __unused = __len - 1;
223 
224 	__stack.__buf = malloc(__bufsz);
225 
226 	arc4random_buf(__stack.__buf, __len);
227 #undef BUF
228 
229 }
230 
231 ATF_TC(arc4random_buf_heap_end);
232 ATF_TC_HEAD(arc4random_buf_heap_end, tc)
233 {
234 }
235 ATF_TC_BODY(arc4random_buf_heap_end, tc)
236 {
237 #define BUF __stack.__buf
238 	struct {
239 		uint8_t padding_l;
240 		unsigned char * __buf;
241 		uint8_t padding_r;
242 	} __stack;
243 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
244 	const size_t __len = 42;
245 	const size_t __idx __unused = __len - 1;
246 
247 	__stack.__buf = malloc(__bufsz);
248 
249 	arc4random_buf(__stack.__buf, __len);
250 #undef BUF
251 
252 }
253 
254 ATF_TC(arc4random_buf_heap_after_end);
255 ATF_TC_HEAD(arc4random_buf_heap_after_end, tc)
256 {
257 }
258 ATF_TC_BODY(arc4random_buf_heap_after_end, tc)
259 {
260 #define BUF __stack.__buf
261 	struct {
262 		uint8_t padding_l;
263 		unsigned char * __buf;
264 		uint8_t padding_r;
265 	} __stack;
266 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
267 	const size_t __len = 42 + 1;
268 	const size_t __idx __unused = __len - 1;
269 	pid_t __child;
270 	int __status;
271 
272 	__child = fork();
273 	ATF_REQUIRE(__child >= 0);
274 	if (__child > 0)
275 		goto monitor;
276 
277 	/* Child */
278 	disable_coredumps();
279 	__stack.__buf = malloc(__bufsz);
280 
281 	arc4random_buf(__stack.__buf, __len);
282 	_exit(EX_SOFTWARE);	/* Should have aborted. */
283 
284 monitor:
285 	while (waitpid(__child, &__status, 0) != __child) {
286 		ATF_REQUIRE_EQ(EINTR, errno);
287 	}
288 
289 	if (!WIFSIGNALED(__status)) {
290 		switch (WEXITSTATUS(__status)) {
291 		case EX_SOFTWARE:
292 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
293 			break;
294 		case EX_OSERR:
295 			atf_tc_fail("setrlimit(2) failed");
296 			break;
297 		default:
298 			atf_tc_fail("child exited with status %d",
299 			    WEXITSTATUS(__status));
300 		}
301 	} else {
302 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
303 	}
304 #undef BUF
305 
306 }
307 
308 ATF_TC(getenv_r_before_end);
309 ATF_TC_HEAD(getenv_r_before_end, tc)
310 {
311 }
312 ATF_TC_BODY(getenv_r_before_end, tc)
313 {
314 #define BUF &__stack.__buf
315 	struct {
316 		uint8_t padding_l;
317 		unsigned char __buf[42];
318 		uint8_t padding_r;
319 	} __stack;
320 	const size_t __bufsz __unused = sizeof(__stack.__buf);
321 	const size_t __len = 42 - 1;
322 	const size_t __idx __unused = __len - 1;
323 
324 	getenv_r("PATH", __stack.__buf, __len);
325 #undef BUF
326 
327 }
328 
329 ATF_TC(getenv_r_end);
330 ATF_TC_HEAD(getenv_r_end, tc)
331 {
332 }
333 ATF_TC_BODY(getenv_r_end, tc)
334 {
335 #define BUF &__stack.__buf
336 	struct {
337 		uint8_t padding_l;
338 		unsigned char __buf[42];
339 		uint8_t padding_r;
340 	} __stack;
341 	const size_t __bufsz __unused = sizeof(__stack.__buf);
342 	const size_t __len = 42;
343 	const size_t __idx __unused = __len - 1;
344 
345 	getenv_r("PATH", __stack.__buf, __len);
346 #undef BUF
347 
348 }
349 
350 ATF_TC(getenv_r_heap_before_end);
351 ATF_TC_HEAD(getenv_r_heap_before_end, tc)
352 {
353 }
354 ATF_TC_BODY(getenv_r_heap_before_end, tc)
355 {
356 #define BUF __stack.__buf
357 	struct {
358 		uint8_t padding_l;
359 		unsigned char * __buf;
360 		uint8_t padding_r;
361 	} __stack;
362 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
363 	const size_t __len = 42 - 1;
364 	const size_t __idx __unused = __len - 1;
365 
366 	__stack.__buf = malloc(__bufsz);
367 
368 	getenv_r("PATH", __stack.__buf, __len);
369 #undef BUF
370 
371 }
372 
373 ATF_TC(getenv_r_heap_end);
374 ATF_TC_HEAD(getenv_r_heap_end, tc)
375 {
376 }
377 ATF_TC_BODY(getenv_r_heap_end, tc)
378 {
379 #define BUF __stack.__buf
380 	struct {
381 		uint8_t padding_l;
382 		unsigned char * __buf;
383 		uint8_t padding_r;
384 	} __stack;
385 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
386 	const size_t __len = 42;
387 	const size_t __idx __unused = __len - 1;
388 
389 	__stack.__buf = malloc(__bufsz);
390 
391 	getenv_r("PATH", __stack.__buf, __len);
392 #undef BUF
393 
394 }
395 
396 ATF_TC(getenv_r_heap_after_end);
397 ATF_TC_HEAD(getenv_r_heap_after_end, tc)
398 {
399 }
400 ATF_TC_BODY(getenv_r_heap_after_end, tc)
401 {
402 #define BUF __stack.__buf
403 	struct {
404 		uint8_t padding_l;
405 		unsigned char * __buf;
406 		uint8_t padding_r;
407 	} __stack;
408 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
409 	const size_t __len = 42 + 1;
410 	const size_t __idx __unused = __len - 1;
411 	pid_t __child;
412 	int __status;
413 
414 	__child = fork();
415 	ATF_REQUIRE(__child >= 0);
416 	if (__child > 0)
417 		goto monitor;
418 
419 	/* Child */
420 	disable_coredumps();
421 	__stack.__buf = malloc(__bufsz);
422 
423 	getenv_r("PATH", __stack.__buf, __len);
424 	_exit(EX_SOFTWARE);	/* Should have aborted. */
425 
426 monitor:
427 	while (waitpid(__child, &__status, 0) != __child) {
428 		ATF_REQUIRE_EQ(EINTR, errno);
429 	}
430 
431 	if (!WIFSIGNALED(__status)) {
432 		switch (WEXITSTATUS(__status)) {
433 		case EX_SOFTWARE:
434 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
435 			break;
436 		case EX_OSERR:
437 			atf_tc_fail("setrlimit(2) failed");
438 			break;
439 		default:
440 			atf_tc_fail("child exited with status %d",
441 			    WEXITSTATUS(__status));
442 		}
443 	} else {
444 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
445 	}
446 #undef BUF
447 
448 }
449 
450 ATF_TC(realpath_before_end);
451 ATF_TC_HEAD(realpath_before_end, tc)
452 {
453 }
454 ATF_TC_BODY(realpath_before_end, tc)
455 {
456 #define BUF &__stack.__buf
457 	struct {
458 		uint8_t padding_l;
459 		unsigned char __buf[PATH_MAX + 1];
460 		uint8_t padding_r;
461 	} __stack;
462 	const size_t __bufsz __unused = sizeof(__stack.__buf);
463 	const size_t __len = PATH_MAX + 1;
464 	const size_t __idx __unused = __len - 1;
465 
466 	realpath(".", __stack.__buf);
467 #undef BUF
468 
469 }
470 
471 ATF_TC(realpath_end);
472 ATF_TC_HEAD(realpath_end, tc)
473 {
474 }
475 ATF_TC_BODY(realpath_end, tc)
476 {
477 #define BUF &__stack.__buf
478 	struct {
479 		uint8_t padding_l;
480 		unsigned char __buf[PATH_MAX];
481 		uint8_t padding_r;
482 	} __stack;
483 	const size_t __bufsz __unused = sizeof(__stack.__buf);
484 	const size_t __len = PATH_MAX;
485 	const size_t __idx __unused = __len - 1;
486 
487 	realpath(".", __stack.__buf);
488 #undef BUF
489 
490 }
491 
492 ATF_TC(realpath_heap_before_end);
493 ATF_TC_HEAD(realpath_heap_before_end, tc)
494 {
495 }
496 ATF_TC_BODY(realpath_heap_before_end, tc)
497 {
498 #define BUF __stack.__buf
499 	struct {
500 		uint8_t padding_l;
501 		unsigned char * __buf;
502 		uint8_t padding_r;
503 	} __stack;
504 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX + 1);
505 	const size_t __len = PATH_MAX + 1;
506 	const size_t __idx __unused = __len - 1;
507 
508 	__stack.__buf = malloc(__bufsz);
509 
510 	realpath(".", __stack.__buf);
511 #undef BUF
512 
513 }
514 
515 ATF_TC(realpath_heap_end);
516 ATF_TC_HEAD(realpath_heap_end, tc)
517 {
518 }
519 ATF_TC_BODY(realpath_heap_end, tc)
520 {
521 #define BUF __stack.__buf
522 	struct {
523 		uint8_t padding_l;
524 		unsigned char * __buf;
525 		uint8_t padding_r;
526 	} __stack;
527 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX);
528 	const size_t __len = PATH_MAX;
529 	const size_t __idx __unused = __len - 1;
530 
531 	__stack.__buf = malloc(__bufsz);
532 
533 	realpath(".", __stack.__buf);
534 #undef BUF
535 
536 }
537 
538 ATF_TC(realpath_heap_after_end);
539 ATF_TC_HEAD(realpath_heap_after_end, tc)
540 {
541 }
542 ATF_TC_BODY(realpath_heap_after_end, tc)
543 {
544 #define BUF __stack.__buf
545 	struct {
546 		uint8_t padding_l;
547 		unsigned char * __buf;
548 		uint8_t padding_r;
549 	} __stack;
550 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX - 1);
551 	const size_t __len = PATH_MAX - 1;
552 	const size_t __idx __unused = __len - 1;
553 	pid_t __child;
554 	int __status;
555 
556 	__child = fork();
557 	ATF_REQUIRE(__child >= 0);
558 	if (__child > 0)
559 		goto monitor;
560 
561 	/* Child */
562 	disable_coredumps();
563 	__stack.__buf = malloc(__bufsz);
564 
565 	realpath(".", __stack.__buf);
566 	_exit(EX_SOFTWARE);	/* Should have aborted. */
567 
568 monitor:
569 	while (waitpid(__child, &__status, 0) != __child) {
570 		ATF_REQUIRE_EQ(EINTR, errno);
571 	}
572 
573 	if (!WIFSIGNALED(__status)) {
574 		switch (WEXITSTATUS(__status)) {
575 		case EX_SOFTWARE:
576 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
577 			break;
578 		case EX_OSERR:
579 			atf_tc_fail("setrlimit(2) failed");
580 			break;
581 		default:
582 			atf_tc_fail("child exited with status %d",
583 			    WEXITSTATUS(__status));
584 		}
585 	} else {
586 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
587 	}
588 #undef BUF
589 
590 }
591 
592 ATF_TP_ADD_TCS(tp)
593 {
594 	ATF_TP_ADD_TC(tp, arc4random_buf_before_end);
595 	ATF_TP_ADD_TC(tp, arc4random_buf_end);
596 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end);
597 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_end);
598 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end);
599 	ATF_TP_ADD_TC(tp, getenv_r_before_end);
600 	ATF_TP_ADD_TC(tp, getenv_r_end);
601 	ATF_TP_ADD_TC(tp, getenv_r_heap_before_end);
602 	ATF_TP_ADD_TC(tp, getenv_r_heap_end);
603 	ATF_TP_ADD_TC(tp, getenv_r_heap_after_end);
604 	ATF_TP_ADD_TC(tp, realpath_before_end);
605 	ATF_TP_ADD_TC(tp, realpath_end);
606 	ATF_TP_ADD_TC(tp, realpath_heap_before_end);
607 	ATF_TP_ADD_TC(tp, realpath_heap_end);
608 	ATF_TP_ADD_TC(tp, realpath_heap_after_end);
609 	return (atf_no_error());
610 }
611