xref: /freebsd/lib/libc/tests/secure/fortify_strings_test.c (revision 062d9380b98663eb2a4a3d7ce9e919e743984060)
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/random.h>
8 #include <sys/resource.h>
9 #include <sys/time.h>
10 #include <sys/wait.h>
11 #include <dirent.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <poll.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <sysexits.h>
22 #include <unistd.h>
23 #include <wchar.h>
24 #include <atf-c.h>
25 
26 static FILE * __unused
27 new_fp(size_t __len)
28 {
29 	static char fpbuf[LINE_MAX];
30 	FILE *fp;
31 
32 	ATF_REQUIRE(__len <= sizeof(fpbuf));
33 
34 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
35 	fpbuf[sizeof(fpbuf) - 1] = '\0';
36 
37 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
38 	ATF_REQUIRE(fp != NULL);
39 
40 	return (fp);
41 }
42 
43 /*
44  * Create a new symlink to use for readlink(2) style tests, we'll just use a
45  * random target name to have something interesting to look at.
46  */
47 static const char * __unused
48 new_symlink(size_t __len)
49 {
50 	static const char linkname[] = "link";
51 	char target[MAXNAMLEN];
52 	int error;
53 
54 	ATF_REQUIRE(__len <= sizeof(target));
55 
56 	arc4random_buf(target, sizeof(target));
57 
58 	error = unlink(linkname);
59 	ATF_REQUIRE(error == 0 || errno == ENOENT);
60 
61 	error = symlink(target, linkname);
62 	ATF_REQUIRE(error == 0);
63 
64 	return (linkname);
65 }
66 
67 /*
68  * Constructs a tmpfile that we can use for testing read(2) and friends.
69  */
70 static int __unused
71 new_tmpfile(void)
72 {
73 	char buf[1024];
74 	ssize_t rv;
75 	size_t written;
76 	int fd;
77 
78 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
79 	ATF_REQUIRE(fd >= 0);
80 
81 	written = 0;
82 	while (written < TMPFILE_SIZE) {
83 		rv = write(fd, buf, sizeof(buf));
84 		ATF_REQUIRE(rv > 0);
85 
86 		written += rv;
87 	}
88 
89 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
90 	return (fd);
91 }
92 
93 static void
94 disable_coredumps(void)
95 {
96 	struct rlimit rl = { 0 };
97 
98 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
99 		_exit(EX_OSERR);
100 }
101 
102 /*
103  * Replaces stdin with a file that we can actually read from, for tests where
104  * we want a FILE * or fd that we can get data from.
105  */
106 static void __unused
107 replace_stdin(void)
108 {
109 	int fd;
110 
111 	fd = new_tmpfile();
112 
113 	(void)dup2(fd, STDIN_FILENO);
114 	if (fd != STDIN_FILENO)
115 		close(fd);
116 }
117 
118 ATF_TC_WITHOUT_HEAD(bcopy_before_end);
119 ATF_TC_BODY(bcopy_before_end, tc)
120 {
121 #define BUF &__stack.__buf
122 	struct {
123 		uint8_t padding_l;
124 		unsigned char __buf[42];
125 		uint8_t padding_r;
126 	} __stack;
127 	const size_t __bufsz __unused = sizeof(__stack.__buf);
128 	const size_t __len = 42 - 1;
129 	const size_t __idx __unused = __len - 1;
130 	char src[__len + 10];
131 
132 	bcopy(src, __stack.__buf, __len);
133 #undef BUF
134 
135 }
136 
137 ATF_TC_WITHOUT_HEAD(bcopy_end);
138 ATF_TC_BODY(bcopy_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 	char src[__len + 10];
150 
151 	bcopy(src, __stack.__buf, __len);
152 #undef BUF
153 
154 }
155 
156 ATF_TC_WITHOUT_HEAD(bcopy_heap_before_end);
157 ATF_TC_BODY(bcopy_heap_before_end, tc)
158 {
159 #define BUF __stack.__buf
160 	struct {
161 		uint8_t padding_l;
162 		unsigned char * __buf;
163 		uint8_t padding_r;
164 	} __stack;
165 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
166 	const size_t __len = 42 - 1;
167 	const size_t __idx __unused = __len - 1;
168 	char src[__len + 10];
169 
170 	__stack.__buf = malloc(__bufsz);
171 
172 	bcopy(src, __stack.__buf, __len);
173 #undef BUF
174 
175 }
176 
177 ATF_TC_WITHOUT_HEAD(bcopy_heap_end);
178 ATF_TC_BODY(bcopy_heap_end, tc)
179 {
180 #define BUF __stack.__buf
181 	struct {
182 		uint8_t padding_l;
183 		unsigned char * __buf;
184 		uint8_t padding_r;
185 	} __stack;
186 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
187 	const size_t __len = 42;
188 	const size_t __idx __unused = __len - 1;
189 	char src[__len + 10];
190 
191 	__stack.__buf = malloc(__bufsz);
192 
193 	bcopy(src, __stack.__buf, __len);
194 #undef BUF
195 
196 }
197 
198 ATF_TC_WITHOUT_HEAD(bcopy_heap_after_end);
199 ATF_TC_BODY(bcopy_heap_after_end, tc)
200 {
201 #define BUF __stack.__buf
202 	struct {
203 		uint8_t padding_l;
204 		unsigned char * __buf;
205 		uint8_t padding_r;
206 	} __stack;
207 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
208 	const size_t __len = 42 + 1;
209 	const size_t __idx __unused = __len - 1;
210 	pid_t __child;
211 	int __status;
212 	char src[__len + 10];
213 
214 	__child = fork();
215 	ATF_REQUIRE(__child >= 0);
216 	if (__child > 0)
217 		goto monitor;
218 
219 	/* Child */
220 	disable_coredumps();
221 	__stack.__buf = malloc(__bufsz);
222 
223 	bcopy(src, __stack.__buf, __len);
224 	_exit(EX_SOFTWARE);	/* Should have aborted. */
225 
226 monitor:
227 	while (waitpid(__child, &__status, 0) != __child) {
228 		ATF_REQUIRE_EQ(EINTR, errno);
229 	}
230 
231 	if (!WIFSIGNALED(__status)) {
232 		switch (WEXITSTATUS(__status)) {
233 		case EX_SOFTWARE:
234 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
235 			break;
236 		case EX_OSERR:
237 			atf_tc_fail("setrlimit(2) failed");
238 			break;
239 		default:
240 			atf_tc_fail("child exited with status %d",
241 			    WEXITSTATUS(__status));
242 		}
243 	} else {
244 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
245 	}
246 #undef BUF
247 
248 }
249 
250 ATF_TC_WITHOUT_HEAD(bzero_before_end);
251 ATF_TC_BODY(bzero_before_end, tc)
252 {
253 #define BUF &__stack.__buf
254 	struct {
255 		uint8_t padding_l;
256 		unsigned char __buf[42];
257 		uint8_t padding_r;
258 	} __stack;
259 	const size_t __bufsz __unused = sizeof(__stack.__buf);
260 	const size_t __len = 42 - 1;
261 	const size_t __idx __unused = __len - 1;
262 
263 	bzero(__stack.__buf, __len);
264 #undef BUF
265 
266 }
267 
268 ATF_TC_WITHOUT_HEAD(bzero_end);
269 ATF_TC_BODY(bzero_end, tc)
270 {
271 #define BUF &__stack.__buf
272 	struct {
273 		uint8_t padding_l;
274 		unsigned char __buf[42];
275 		uint8_t padding_r;
276 	} __stack;
277 	const size_t __bufsz __unused = sizeof(__stack.__buf);
278 	const size_t __len = 42;
279 	const size_t __idx __unused = __len - 1;
280 
281 	bzero(__stack.__buf, __len);
282 #undef BUF
283 
284 }
285 
286 ATF_TC_WITHOUT_HEAD(bzero_heap_before_end);
287 ATF_TC_BODY(bzero_heap_before_end, tc)
288 {
289 #define BUF __stack.__buf
290 	struct {
291 		uint8_t padding_l;
292 		unsigned char * __buf;
293 		uint8_t padding_r;
294 	} __stack;
295 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
296 	const size_t __len = 42 - 1;
297 	const size_t __idx __unused = __len - 1;
298 
299 	__stack.__buf = malloc(__bufsz);
300 
301 	bzero(__stack.__buf, __len);
302 #undef BUF
303 
304 }
305 
306 ATF_TC_WITHOUT_HEAD(bzero_heap_end);
307 ATF_TC_BODY(bzero_heap_end, tc)
308 {
309 #define BUF __stack.__buf
310 	struct {
311 		uint8_t padding_l;
312 		unsigned char * __buf;
313 		uint8_t padding_r;
314 	} __stack;
315 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
316 	const size_t __len = 42;
317 	const size_t __idx __unused = __len - 1;
318 
319 	__stack.__buf = malloc(__bufsz);
320 
321 	bzero(__stack.__buf, __len);
322 #undef BUF
323 
324 }
325 
326 ATF_TC_WITHOUT_HEAD(bzero_heap_after_end);
327 ATF_TC_BODY(bzero_heap_after_end, tc)
328 {
329 #define BUF __stack.__buf
330 	struct {
331 		uint8_t padding_l;
332 		unsigned char * __buf;
333 		uint8_t padding_r;
334 	} __stack;
335 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
336 	const size_t __len = 42 + 1;
337 	const size_t __idx __unused = __len - 1;
338 	pid_t __child;
339 	int __status;
340 
341 	__child = fork();
342 	ATF_REQUIRE(__child >= 0);
343 	if (__child > 0)
344 		goto monitor;
345 
346 	/* Child */
347 	disable_coredumps();
348 	__stack.__buf = malloc(__bufsz);
349 
350 	bzero(__stack.__buf, __len);
351 	_exit(EX_SOFTWARE);	/* Should have aborted. */
352 
353 monitor:
354 	while (waitpid(__child, &__status, 0) != __child) {
355 		ATF_REQUIRE_EQ(EINTR, errno);
356 	}
357 
358 	if (!WIFSIGNALED(__status)) {
359 		switch (WEXITSTATUS(__status)) {
360 		case EX_SOFTWARE:
361 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
362 			break;
363 		case EX_OSERR:
364 			atf_tc_fail("setrlimit(2) failed");
365 			break;
366 		default:
367 			atf_tc_fail("child exited with status %d",
368 			    WEXITSTATUS(__status));
369 		}
370 	} else {
371 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
372 	}
373 #undef BUF
374 
375 }
376 
377 ATF_TC_WITHOUT_HEAD(explicit_bzero_before_end);
378 ATF_TC_BODY(explicit_bzero_before_end, tc)
379 {
380 #define BUF &__stack.__buf
381 	struct {
382 		uint8_t padding_l;
383 		unsigned char __buf[42];
384 		uint8_t padding_r;
385 	} __stack;
386 	const size_t __bufsz __unused = sizeof(__stack.__buf);
387 	const size_t __len = 42 - 1;
388 	const size_t __idx __unused = __len - 1;
389 
390 	explicit_bzero(__stack.__buf, __len);
391 #undef BUF
392 
393 }
394 
395 ATF_TC_WITHOUT_HEAD(explicit_bzero_end);
396 ATF_TC_BODY(explicit_bzero_end, tc)
397 {
398 #define BUF &__stack.__buf
399 	struct {
400 		uint8_t padding_l;
401 		unsigned char __buf[42];
402 		uint8_t padding_r;
403 	} __stack;
404 	const size_t __bufsz __unused = sizeof(__stack.__buf);
405 	const size_t __len = 42;
406 	const size_t __idx __unused = __len - 1;
407 
408 	explicit_bzero(__stack.__buf, __len);
409 #undef BUF
410 
411 }
412 
413 ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_before_end);
414 ATF_TC_BODY(explicit_bzero_heap_before_end, tc)
415 {
416 #define BUF __stack.__buf
417 	struct {
418 		uint8_t padding_l;
419 		unsigned char * __buf;
420 		uint8_t padding_r;
421 	} __stack;
422 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
423 	const size_t __len = 42 - 1;
424 	const size_t __idx __unused = __len - 1;
425 
426 	__stack.__buf = malloc(__bufsz);
427 
428 	explicit_bzero(__stack.__buf, __len);
429 #undef BUF
430 
431 }
432 
433 ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_end);
434 ATF_TC_BODY(explicit_bzero_heap_end, tc)
435 {
436 #define BUF __stack.__buf
437 	struct {
438 		uint8_t padding_l;
439 		unsigned char * __buf;
440 		uint8_t padding_r;
441 	} __stack;
442 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
443 	const size_t __len = 42;
444 	const size_t __idx __unused = __len - 1;
445 
446 	__stack.__buf = malloc(__bufsz);
447 
448 	explicit_bzero(__stack.__buf, __len);
449 #undef BUF
450 
451 }
452 
453 ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_after_end);
454 ATF_TC_BODY(explicit_bzero_heap_after_end, tc)
455 {
456 #define BUF __stack.__buf
457 	struct {
458 		uint8_t padding_l;
459 		unsigned char * __buf;
460 		uint8_t padding_r;
461 	} __stack;
462 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
463 	const size_t __len = 42 + 1;
464 	const size_t __idx __unused = __len - 1;
465 	pid_t __child;
466 	int __status;
467 
468 	__child = fork();
469 	ATF_REQUIRE(__child >= 0);
470 	if (__child > 0)
471 		goto monitor;
472 
473 	/* Child */
474 	disable_coredumps();
475 	__stack.__buf = malloc(__bufsz);
476 
477 	explicit_bzero(__stack.__buf, __len);
478 	_exit(EX_SOFTWARE);	/* Should have aborted. */
479 
480 monitor:
481 	while (waitpid(__child, &__status, 0) != __child) {
482 		ATF_REQUIRE_EQ(EINTR, errno);
483 	}
484 
485 	if (!WIFSIGNALED(__status)) {
486 		switch (WEXITSTATUS(__status)) {
487 		case EX_SOFTWARE:
488 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
489 			break;
490 		case EX_OSERR:
491 			atf_tc_fail("setrlimit(2) failed");
492 			break;
493 		default:
494 			atf_tc_fail("child exited with status %d",
495 			    WEXITSTATUS(__status));
496 		}
497 	} else {
498 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
499 	}
500 #undef BUF
501 
502 }
503 
504 ATF_TP_ADD_TCS(tp)
505 {
506 	ATF_TP_ADD_TC(tp, bcopy_before_end);
507 	ATF_TP_ADD_TC(tp, bcopy_end);
508 	ATF_TP_ADD_TC(tp, bcopy_heap_before_end);
509 	ATF_TP_ADD_TC(tp, bcopy_heap_end);
510 	ATF_TP_ADD_TC(tp, bcopy_heap_after_end);
511 	ATF_TP_ADD_TC(tp, bzero_before_end);
512 	ATF_TP_ADD_TC(tp, bzero_end);
513 	ATF_TP_ADD_TC(tp, bzero_heap_before_end);
514 	ATF_TP_ADD_TC(tp, bzero_heap_end);
515 	ATF_TP_ADD_TC(tp, bzero_heap_after_end);
516 	ATF_TP_ADD_TC(tp, explicit_bzero_before_end);
517 	ATF_TP_ADD_TC(tp, explicit_bzero_end);
518 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_before_end);
519 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_end);
520 	ATF_TP_ADD_TC(tp, explicit_bzero_heap_after_end);
521 	return (atf_no_error());
522 }
523