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