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