xref: /freebsd/lib/libc/tests/secure/fortify_strings_test.c (revision 22178cb29f03a3b7bf919f3605e0cd5d6b18fa0a)
1 /* @generated by `generate-fortify-tests.lua "strings"` */
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
new_fp(size_t __len)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
new_symlink(size_t __len)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
new_socket(int sock[2])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
new_tmpfile(void)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
disable_coredumps(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
replace_stdin(void)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(bcopy_before_end);
ATF_TC_HEAD(bcopy_before_end,tc)167 ATF_TC_HEAD(bcopy_before_end, tc)
168 {
169 }
ATF_TC_BODY(bcopy_before_end,tc)170 ATF_TC_BODY(bcopy_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 	char src[__len + 10];
182 
183 	bcopy(src, __stack.__buf, __len);
184 #undef BUF
185 
186 }
187 
188 ATF_TC(bcopy_end);
ATF_TC_HEAD(bcopy_end,tc)189 ATF_TC_HEAD(bcopy_end, tc)
190 {
191 }
ATF_TC_BODY(bcopy_end,tc)192 ATF_TC_BODY(bcopy_end, tc)
193 {
194 #define BUF &__stack.__buf
195 	struct {
196 		uint8_t padding_l;
197 		unsigned char __buf[42];
198 		uint8_t padding_r;
199 	} __stack;
200 	const size_t __bufsz __unused = sizeof(__stack.__buf);
201 	const size_t __len = 42;
202 	const size_t __idx __unused = __len - 1;
203 	char src[__len + 10];
204 
205 	bcopy(src, __stack.__buf, __len);
206 #undef BUF
207 
208 }
209 
210 ATF_TC(bcopy_heap_before_end);
ATF_TC_HEAD(bcopy_heap_before_end,tc)211 ATF_TC_HEAD(bcopy_heap_before_end, tc)
212 {
213 }
ATF_TC_BODY(bcopy_heap_before_end,tc)214 ATF_TC_BODY(bcopy_heap_before_end, tc)
215 {
216 #define BUF __stack.__buf
217 	struct {
218 		uint8_t padding_l;
219 		unsigned char * __buf;
220 		uint8_t padding_r;
221 	} __stack;
222 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
223 	const size_t __len = 42 - 1;
224 	const size_t __idx __unused = __len - 1;
225 	char src[__len + 10];
226 
227 	__stack.__buf = malloc(__bufsz);
228 
229 	bcopy(src, __stack.__buf, __len);
230 #undef BUF
231 
232 }
233 
234 ATF_TC(bcopy_heap_end);
ATF_TC_HEAD(bcopy_heap_end,tc)235 ATF_TC_HEAD(bcopy_heap_end, tc)
236 {
237 }
ATF_TC_BODY(bcopy_heap_end,tc)238 ATF_TC_BODY(bcopy_heap_end, tc)
239 {
240 #define BUF __stack.__buf
241 	struct {
242 		uint8_t padding_l;
243 		unsigned char * __buf;
244 		uint8_t padding_r;
245 	} __stack;
246 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
247 	const size_t __len = 42;
248 	const size_t __idx __unused = __len - 1;
249 	char src[__len + 10];
250 
251 	__stack.__buf = malloc(__bufsz);
252 
253 	bcopy(src, __stack.__buf, __len);
254 #undef BUF
255 
256 }
257 
258 ATF_TC(bcopy_heap_after_end);
ATF_TC_HEAD(bcopy_heap_after_end,tc)259 ATF_TC_HEAD(bcopy_heap_after_end, tc)
260 {
261 }
ATF_TC_BODY(bcopy_heap_after_end,tc)262 ATF_TC_BODY(bcopy_heap_after_end, tc)
263 {
264 #define BUF __stack.__buf
265 	struct {
266 		uint8_t padding_l;
267 		unsigned char * __buf;
268 		uint8_t padding_r;
269 	} __stack;
270 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
271 	const size_t __len = 42 + 1;
272 	const size_t __idx __unused = __len - 1;
273 	pid_t __child;
274 	int __status;
275 	char src[__len + 10];
276 
277 	__child = fork();
278 	ATF_REQUIRE(__child >= 0);
279 	if (__child > 0)
280 		goto monitor;
281 
282 	/* Child */
283 	disable_coredumps();
284 	__stack.__buf = malloc(__bufsz);
285 
286 	bcopy(src, __stack.__buf, __len);
287 	_exit(EX_SOFTWARE);	/* Should have aborted. */
288 
289 monitor:
290 	while (waitpid(__child, &__status, 0) != __child) {
291 		ATF_REQUIRE_EQ(EINTR, errno);
292 	}
293 
294 	if (!WIFSIGNALED(__status)) {
295 		switch (WEXITSTATUS(__status)) {
296 		case EX_SOFTWARE:
297 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
298 			break;
299 		case EX_OSERR:
300 			atf_tc_fail("setrlimit(2) failed");
301 			break;
302 		default:
303 			atf_tc_fail("child exited with status %d",
304 			    WEXITSTATUS(__status));
305 		}
306 	} else {
307 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
308 	}
309 #undef BUF
310 
311 }
312 
313 ATF_TC(bzero_before_end);
ATF_TC_HEAD(bzero_before_end,tc)314 ATF_TC_HEAD(bzero_before_end, tc)
315 {
316 }
ATF_TC_BODY(bzero_before_end,tc)317 ATF_TC_BODY(bzero_before_end, tc)
318 {
319 #define BUF &__stack.__buf
320 	struct {
321 		uint8_t padding_l;
322 		unsigned char __buf[42];
323 		uint8_t padding_r;
324 	} __stack;
325 	const size_t __bufsz __unused = sizeof(__stack.__buf);
326 	const size_t __len = 42 - 1;
327 	const size_t __idx __unused = __len - 1;
328 
329 	bzero(__stack.__buf, __len);
330 #undef BUF
331 
332 }
333 
334 ATF_TC(bzero_end);
ATF_TC_HEAD(bzero_end,tc)335 ATF_TC_HEAD(bzero_end, tc)
336 {
337 }
ATF_TC_BODY(bzero_end,tc)338 ATF_TC_BODY(bzero_end, tc)
339 {
340 #define BUF &__stack.__buf
341 	struct {
342 		uint8_t padding_l;
343 		unsigned char __buf[42];
344 		uint8_t padding_r;
345 	} __stack;
346 	const size_t __bufsz __unused = sizeof(__stack.__buf);
347 	const size_t __len = 42;
348 	const size_t __idx __unused = __len - 1;
349 
350 	bzero(__stack.__buf, __len);
351 #undef BUF
352 
353 }
354 
355 ATF_TC(bzero_heap_before_end);
ATF_TC_HEAD(bzero_heap_before_end,tc)356 ATF_TC_HEAD(bzero_heap_before_end, tc)
357 {
358 }
ATF_TC_BODY(bzero_heap_before_end,tc)359 ATF_TC_BODY(bzero_heap_before_end, tc)
360 {
361 #define BUF __stack.__buf
362 	struct {
363 		uint8_t padding_l;
364 		unsigned char * __buf;
365 		uint8_t padding_r;
366 	} __stack;
367 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
368 	const size_t __len = 42 - 1;
369 	const size_t __idx __unused = __len - 1;
370 
371 	__stack.__buf = malloc(__bufsz);
372 
373 	bzero(__stack.__buf, __len);
374 #undef BUF
375 
376 }
377 
378 ATF_TC(bzero_heap_end);
ATF_TC_HEAD(bzero_heap_end,tc)379 ATF_TC_HEAD(bzero_heap_end, tc)
380 {
381 }
ATF_TC_BODY(bzero_heap_end,tc)382 ATF_TC_BODY(bzero_heap_end, tc)
383 {
384 #define BUF __stack.__buf
385 	struct {
386 		uint8_t padding_l;
387 		unsigned char * __buf;
388 		uint8_t padding_r;
389 	} __stack;
390 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
391 	const size_t __len = 42;
392 	const size_t __idx __unused = __len - 1;
393 
394 	__stack.__buf = malloc(__bufsz);
395 
396 	bzero(__stack.__buf, __len);
397 #undef BUF
398 
399 }
400 
401 ATF_TC(bzero_heap_after_end);
ATF_TC_HEAD(bzero_heap_after_end,tc)402 ATF_TC_HEAD(bzero_heap_after_end, tc)
403 {
404 }
ATF_TC_BODY(bzero_heap_after_end,tc)405 ATF_TC_BODY(bzero_heap_after_end, tc)
406 {
407 #define BUF __stack.__buf
408 	struct {
409 		uint8_t padding_l;
410 		unsigned char * __buf;
411 		uint8_t padding_r;
412 	} __stack;
413 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
414 	const size_t __len = 42 + 1;
415 	const size_t __idx __unused = __len - 1;
416 	pid_t __child;
417 	int __status;
418 
419 	__child = fork();
420 	ATF_REQUIRE(__child >= 0);
421 	if (__child > 0)
422 		goto monitor;
423 
424 	/* Child */
425 	disable_coredumps();
426 	__stack.__buf = malloc(__bufsz);
427 
428 	bzero(__stack.__buf, __len);
429 	_exit(EX_SOFTWARE);	/* Should have aborted. */
430 
431 monitor:
432 	while (waitpid(__child, &__status, 0) != __child) {
433 		ATF_REQUIRE_EQ(EINTR, errno);
434 	}
435 
436 	if (!WIFSIGNALED(__status)) {
437 		switch (WEXITSTATUS(__status)) {
438 		case EX_SOFTWARE:
439 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
440 			break;
441 		case EX_OSERR:
442 			atf_tc_fail("setrlimit(2) failed");
443 			break;
444 		default:
445 			atf_tc_fail("child exited with status %d",
446 			    WEXITSTATUS(__status));
447 		}
448 	} else {
449 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
450 	}
451 #undef BUF
452 
453 }
454 
455 ATF_TC(explicit_bzero_before_end);
ATF_TC_HEAD(explicit_bzero_before_end,tc)456 ATF_TC_HEAD(explicit_bzero_before_end, tc)
457 {
458 }
ATF_TC_BODY(explicit_bzero_before_end,tc)459 ATF_TC_BODY(explicit_bzero_before_end, tc)
460 {
461 #define BUF &__stack.__buf
462 	struct {
463 		uint8_t padding_l;
464 		unsigned char __buf[42];
465 		uint8_t padding_r;
466 	} __stack;
467 	const size_t __bufsz __unused = sizeof(__stack.__buf);
468 	const size_t __len = 42 - 1;
469 	const size_t __idx __unused = __len - 1;
470 
471 	explicit_bzero(__stack.__buf, __len);
472 #undef BUF
473 
474 }
475 
476 ATF_TC(explicit_bzero_end);
ATF_TC_HEAD(explicit_bzero_end,tc)477 ATF_TC_HEAD(explicit_bzero_end, tc)
478 {
479 }
ATF_TC_BODY(explicit_bzero_end,tc)480 ATF_TC_BODY(explicit_bzero_end, tc)
481 {
482 #define BUF &__stack.__buf
483 	struct {
484 		uint8_t padding_l;
485 		unsigned char __buf[42];
486 		uint8_t padding_r;
487 	} __stack;
488 	const size_t __bufsz __unused = sizeof(__stack.__buf);
489 	const size_t __len = 42;
490 	const size_t __idx __unused = __len - 1;
491 
492 	explicit_bzero(__stack.__buf, __len);
493 #undef BUF
494 
495 }
496 
497 ATF_TC(explicit_bzero_heap_before_end);
ATF_TC_HEAD(explicit_bzero_heap_before_end,tc)498 ATF_TC_HEAD(explicit_bzero_heap_before_end, tc)
499 {
500 }
ATF_TC_BODY(explicit_bzero_heap_before_end,tc)501 ATF_TC_BODY(explicit_bzero_heap_before_end, tc)
502 {
503 #define BUF __stack.__buf
504 	struct {
505 		uint8_t padding_l;
506 		unsigned char * __buf;
507 		uint8_t padding_r;
508 	} __stack;
509 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
510 	const size_t __len = 42 - 1;
511 	const size_t __idx __unused = __len - 1;
512 
513 	__stack.__buf = malloc(__bufsz);
514 
515 	explicit_bzero(__stack.__buf, __len);
516 #undef BUF
517 
518 }
519 
520 ATF_TC(explicit_bzero_heap_end);
ATF_TC_HEAD(explicit_bzero_heap_end,tc)521 ATF_TC_HEAD(explicit_bzero_heap_end, tc)
522 {
523 }
ATF_TC_BODY(explicit_bzero_heap_end,tc)524 ATF_TC_BODY(explicit_bzero_heap_end, tc)
525 {
526 #define BUF __stack.__buf
527 	struct {
528 		uint8_t padding_l;
529 		unsigned char * __buf;
530 		uint8_t padding_r;
531 	} __stack;
532 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
533 	const size_t __len = 42;
534 	const size_t __idx __unused = __len - 1;
535 
536 	__stack.__buf = malloc(__bufsz);
537 
538 	explicit_bzero(__stack.__buf, __len);
539 #undef BUF
540 
541 }
542 
543 ATF_TC(explicit_bzero_heap_after_end);
ATF_TC_HEAD(explicit_bzero_heap_after_end,tc)544 ATF_TC_HEAD(explicit_bzero_heap_after_end, tc)
545 {
546 }
ATF_TC_BODY(explicit_bzero_heap_after_end,tc)547 ATF_TC_BODY(explicit_bzero_heap_after_end, tc)
548 {
549 #define BUF __stack.__buf
550 	struct {
551 		uint8_t padding_l;
552 		unsigned char * __buf;
553 		uint8_t padding_r;
554 	} __stack;
555 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
556 	const size_t __len = 42 + 1;
557 	const size_t __idx __unused = __len - 1;
558 	pid_t __child;
559 	int __status;
560 
561 	__child = fork();
562 	ATF_REQUIRE(__child >= 0);
563 	if (__child > 0)
564 		goto monitor;
565 
566 	/* Child */
567 	disable_coredumps();
568 	__stack.__buf = malloc(__bufsz);
569 
570 	explicit_bzero(__stack.__buf, __len);
571 	_exit(EX_SOFTWARE);	/* Should have aborted. */
572 
573 monitor:
574 	while (waitpid(__child, &__status, 0) != __child) {
575 		ATF_REQUIRE_EQ(EINTR, errno);
576 	}
577 
578 	if (!WIFSIGNALED(__status)) {
579 		switch (WEXITSTATUS(__status)) {
580 		case EX_SOFTWARE:
581 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
582 			break;
583 		case EX_OSERR:
584 			atf_tc_fail("setrlimit(2) failed");
585 			break;
586 		default:
587 			atf_tc_fail("child exited with status %d",
588 			    WEXITSTATUS(__status));
589 		}
590 	} else {
591 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
592 	}
593 #undef BUF
594 
595 }
596 
ATF_TP_ADD_TCS(tp)597 ATF_TP_ADD_TCS(tp)
598 {
599 	ATF_TP_ADD_TC(tp, bcopy_before_end);
600 	ATF_TP_ADD_TC(tp, bcopy_end);
601 	ATF_TP_ADD_TC(tp, bcopy_heap_before_end);
602 	ATF_TP_ADD_TC(tp, bcopy_heap_end);
603 	ATF_TP_ADD_TC(tp, bcopy_heap_after_end);
604 	ATF_TP_ADD_TC(tp, bzero_before_end);
605 	ATF_TP_ADD_TC(tp, bzero_end);
606 	ATF_TP_ADD_TC(tp, bzero_heap_before_end);
607 	ATF_TP_ADD_TC(tp, bzero_heap_end);
608 	ATF_TP_ADD_TC(tp, bzero_heap_after_end);
609 	ATF_TP_ADD_TC(tp, explicit_bzero_before_end);
610 	ATF_TP_ADD_TC(tp, explicit_bzero_end);
611 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_before_end);
612 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_end);
613 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_after_end);
614 	return (atf_no_error());
615 }
616