xref: /freebsd/lib/libc/tests/secure/fortify_poll_test.c (revision 1f155d48f878495d31592c59cab82f975c210ad8)
188276dfbSKyle Evans /* @generated by `generate-fortify-tests.lua "poll"` */
288276dfbSKyle Evans 
388276dfbSKyle Evans #define	_FORTIFY_SOURCE	2
488276dfbSKyle Evans #define	TMPFILE_SIZE	(1024 * 32)
588276dfbSKyle Evans 
688276dfbSKyle Evans #include <sys/param.h>
7062d9380SKyle Evans #include <sys/random.h>
888276dfbSKyle Evans #include <sys/resource.h>
92aba0eeaSKyle Evans #include <sys/select.h>
10*1f155d48SKyle Evans #include <sys/socket.h>
1188276dfbSKyle Evans #include <sys/time.h>
121ace24b3SKyle Evans #include <sys/uio.h>
1388276dfbSKyle Evans #include <sys/wait.h>
1488276dfbSKyle Evans #include <dirent.h>
1588276dfbSKyle Evans #include <errno.h>
1688276dfbSKyle Evans #include <fcntl.h>
1788276dfbSKyle Evans #include <limits.h>
1888276dfbSKyle Evans #include <poll.h>
1988276dfbSKyle Evans #include <signal.h>
2088276dfbSKyle Evans #include <stdio.h>
2188276dfbSKyle Evans #include <stdlib.h>
2288276dfbSKyle Evans #include <string.h>
2388276dfbSKyle Evans #include <strings.h>
2488276dfbSKyle Evans #include <sysexits.h>
2588276dfbSKyle Evans #include <unistd.h>
26b53d7aa8SKyle Evans #include <wchar.h>
2788276dfbSKyle Evans #include <atf-c.h>
2888276dfbSKyle Evans 
2988276dfbSKyle Evans static FILE * __unused
new_fp(size_t __len)3088276dfbSKyle Evans new_fp(size_t __len)
3188276dfbSKyle Evans {
3288276dfbSKyle Evans 	static char fpbuf[LINE_MAX];
3388276dfbSKyle Evans 	FILE *fp;
3488276dfbSKyle Evans 
3588276dfbSKyle Evans 	ATF_REQUIRE(__len <= sizeof(fpbuf));
3688276dfbSKyle Evans 
3788276dfbSKyle Evans 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
3888276dfbSKyle Evans 	fpbuf[sizeof(fpbuf) - 1] = '\0';
3988276dfbSKyle Evans 
4088276dfbSKyle Evans 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
4188276dfbSKyle Evans 	ATF_REQUIRE(fp != NULL);
4288276dfbSKyle Evans 
4388276dfbSKyle Evans 	return (fp);
4488276dfbSKyle Evans }
4588276dfbSKyle Evans 
4688276dfbSKyle Evans /*
4788276dfbSKyle Evans  * Create a new symlink to use for readlink(2) style tests, we'll just use a
4888276dfbSKyle Evans  * random target name to have something interesting to look at.
4988276dfbSKyle Evans  */
5088276dfbSKyle Evans static const char * __unused
new_symlink(size_t __len)5188276dfbSKyle Evans new_symlink(size_t __len)
5288276dfbSKyle Evans {
5388276dfbSKyle Evans 	static const char linkname[] = "link";
5488276dfbSKyle Evans 	char target[MAXNAMLEN];
5588276dfbSKyle Evans 	int error;
5688276dfbSKyle Evans 
5788276dfbSKyle Evans 	ATF_REQUIRE(__len <= sizeof(target));
5888276dfbSKyle Evans 
5988276dfbSKyle Evans 	arc4random_buf(target, sizeof(target));
6088276dfbSKyle Evans 
6188276dfbSKyle Evans 	error = unlink(linkname);
6288276dfbSKyle Evans 	ATF_REQUIRE(error == 0 || errno == ENOENT);
6388276dfbSKyle Evans 
6488276dfbSKyle Evans 	error = symlink(target, linkname);
6588276dfbSKyle Evans 	ATF_REQUIRE(error == 0);
6688276dfbSKyle Evans 
6788276dfbSKyle Evans 	return (linkname);
6888276dfbSKyle Evans }
6988276dfbSKyle Evans 
7088276dfbSKyle Evans /*
71*1f155d48SKyle Evans  * For our purposes, first descriptor will be the reader; we'll send both
72*1f155d48SKyle Evans  * raw data and a control message over it so that the result can be used for
73*1f155d48SKyle Evans  * any of our recv*() tests.
74*1f155d48SKyle Evans  */
75*1f155d48SKyle Evans static void __unused
new_socket(int sock[2])76*1f155d48SKyle Evans new_socket(int sock[2])
77*1f155d48SKyle Evans {
78*1f155d48SKyle Evans 	unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
79*1f155d48SKyle Evans 	static char sockbuf[256];
80*1f155d48SKyle Evans 	ssize_t rv;
81*1f155d48SKyle Evans 	size_t total = 0;
82*1f155d48SKyle Evans 	struct msghdr hdr = { 0 };
83*1f155d48SKyle Evans 	struct cmsghdr *cmsg;
84*1f155d48SKyle Evans 	int error, fd;
85*1f155d48SKyle Evans 
86*1f155d48SKyle Evans 	error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
87*1f155d48SKyle Evans 	ATF_REQUIRE(error == 0);
88*1f155d48SKyle Evans 
89*1f155d48SKyle Evans 	while (total != sizeof(sockbuf)) {
90*1f155d48SKyle Evans 		rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
91*1f155d48SKyle Evans 
92*1f155d48SKyle Evans 		ATF_REQUIRE_MSG(rv > 0,
93*1f155d48SKyle Evans 		    "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
94*1f155d48SKyle Evans 		    rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
95*1f155d48SKyle Evans 		ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
96*1f155d48SKyle Evans 		    "%zd exceeds total %zu", rv, sizeof(sockbuf));
97*1f155d48SKyle Evans 		total += rv;
98*1f155d48SKyle Evans 	}
99*1f155d48SKyle Evans 
100*1f155d48SKyle Evans 	hdr.msg_control = ctrl;
101*1f155d48SKyle Evans 	hdr.msg_controllen = sizeof(ctrl);
102*1f155d48SKyle Evans 
103*1f155d48SKyle Evans 	cmsg = CMSG_FIRSTHDR(&hdr);
104*1f155d48SKyle Evans 	cmsg->cmsg_level = SOL_SOCKET;
105*1f155d48SKyle Evans 	cmsg->cmsg_type = SCM_RIGHTS;
106*1f155d48SKyle Evans 	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
107*1f155d48SKyle Evans 	fd = STDIN_FILENO;
108*1f155d48SKyle Evans 	memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
109*1f155d48SKyle Evans 
110*1f155d48SKyle Evans 	error = sendmsg(sock[1], &hdr, 0);
111*1f155d48SKyle Evans 	ATF_REQUIRE(error != -1);
112*1f155d48SKyle Evans }
113*1f155d48SKyle Evans 
114*1f155d48SKyle Evans /*
11588276dfbSKyle Evans  * Constructs a tmpfile that we can use for testing read(2) and friends.
11688276dfbSKyle Evans  */
11788276dfbSKyle Evans static int __unused
new_tmpfile(void)11888276dfbSKyle Evans new_tmpfile(void)
11988276dfbSKyle Evans {
12088276dfbSKyle Evans 	char buf[1024];
12188276dfbSKyle Evans 	ssize_t rv;
12288276dfbSKyle Evans 	size_t written;
12388276dfbSKyle Evans 	int fd;
12488276dfbSKyle Evans 
12588276dfbSKyle Evans 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
12688276dfbSKyle Evans 	ATF_REQUIRE(fd >= 0);
12788276dfbSKyle Evans 
12888276dfbSKyle Evans 	written = 0;
12988276dfbSKyle Evans 	while (written < TMPFILE_SIZE) {
13088276dfbSKyle Evans 		rv = write(fd, buf, sizeof(buf));
13188276dfbSKyle Evans 		ATF_REQUIRE(rv > 0);
13288276dfbSKyle Evans 
13388276dfbSKyle Evans 		written += rv;
13488276dfbSKyle Evans 	}
13588276dfbSKyle Evans 
13688276dfbSKyle Evans 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
13788276dfbSKyle Evans 	return (fd);
13888276dfbSKyle Evans }
13988276dfbSKyle Evans 
14088276dfbSKyle Evans static void
disable_coredumps(void)14188276dfbSKyle Evans disable_coredumps(void)
14288276dfbSKyle Evans {
14388276dfbSKyle Evans 	struct rlimit rl = { 0 };
14488276dfbSKyle Evans 
14588276dfbSKyle Evans 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
14688276dfbSKyle Evans 		_exit(EX_OSERR);
14788276dfbSKyle Evans }
14888276dfbSKyle Evans 
14988276dfbSKyle Evans /*
15088276dfbSKyle Evans  * Replaces stdin with a file that we can actually read from, for tests where
15188276dfbSKyle Evans  * we want a FILE * or fd that we can get data from.
15288276dfbSKyle Evans  */
15388276dfbSKyle Evans static void __unused
replace_stdin(void)15488276dfbSKyle Evans replace_stdin(void)
15588276dfbSKyle Evans {
15688276dfbSKyle Evans 	int fd;
15788276dfbSKyle Evans 
15888276dfbSKyle Evans 	fd = new_tmpfile();
15988276dfbSKyle Evans 
16088276dfbSKyle Evans 	(void)dup2(fd, STDIN_FILENO);
16188276dfbSKyle Evans 	if (fd != STDIN_FILENO)
16288276dfbSKyle Evans 		close(fd);
16388276dfbSKyle Evans }
16488276dfbSKyle Evans 
16588276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_before_end);
ATF_TC_BODY(poll_before_end,tc)16688276dfbSKyle Evans ATF_TC_BODY(poll_before_end, tc)
16788276dfbSKyle Evans {
16888276dfbSKyle Evans #define BUF &__stack.__buf
16988276dfbSKyle Evans 	struct {
17088276dfbSKyle Evans 		uint8_t padding_l;
17188276dfbSKyle Evans 		struct pollfd __buf[4];
17288276dfbSKyle Evans 		uint8_t padding_r;
17388276dfbSKyle Evans 	} __stack;
17488276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
17588276dfbSKyle Evans 	const size_t __len = 4 - 1;
17688276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
17788276dfbSKyle Evans 
17888276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
17988276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
18088276dfbSKyle Evans 	}
18188276dfbSKyle Evans 
18288276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
18388276dfbSKyle Evans #undef BUF
18488276dfbSKyle Evans 
18588276dfbSKyle Evans }
18688276dfbSKyle Evans 
18788276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_end);
ATF_TC_BODY(poll_end,tc)18888276dfbSKyle Evans ATF_TC_BODY(poll_end, tc)
18988276dfbSKyle Evans {
19088276dfbSKyle Evans #define BUF &__stack.__buf
19188276dfbSKyle Evans 	struct {
19288276dfbSKyle Evans 		uint8_t padding_l;
19388276dfbSKyle Evans 		struct pollfd __buf[4];
19488276dfbSKyle Evans 		uint8_t padding_r;
19588276dfbSKyle Evans 	} __stack;
19688276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
19788276dfbSKyle Evans 	const size_t __len = 4;
19888276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
19988276dfbSKyle Evans 
20088276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
20188276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
20288276dfbSKyle Evans 	}
20388276dfbSKyle Evans 
20488276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
20588276dfbSKyle Evans #undef BUF
20688276dfbSKyle Evans 
20788276dfbSKyle Evans }
20888276dfbSKyle Evans 
20988276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_after_end);
ATF_TC_BODY(poll_after_end,tc)21088276dfbSKyle Evans ATF_TC_BODY(poll_after_end, tc)
21188276dfbSKyle Evans {
21288276dfbSKyle Evans #define BUF &__stack.__buf
21388276dfbSKyle Evans 	struct {
21488276dfbSKyle Evans 		uint8_t padding_l;
21588276dfbSKyle Evans 		struct pollfd __buf[4];
21688276dfbSKyle Evans 		uint8_t padding_r;
21788276dfbSKyle Evans 	} __stack;
21888276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
21988276dfbSKyle Evans 	const size_t __len = 4 + 1;
22088276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
22188276dfbSKyle Evans 	pid_t __child;
22288276dfbSKyle Evans 	int __status;
22388276dfbSKyle Evans 
22488276dfbSKyle Evans 	__child = fork();
22588276dfbSKyle Evans 	ATF_REQUIRE(__child >= 0);
22688276dfbSKyle Evans 	if (__child > 0)
22788276dfbSKyle Evans 		goto monitor;
22888276dfbSKyle Evans 
22988276dfbSKyle Evans 	/* Child */
23088276dfbSKyle Evans 	disable_coredumps();
23188276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
23288276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
23388276dfbSKyle Evans 	}
23488276dfbSKyle Evans 
23588276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
23688276dfbSKyle Evans 	_exit(EX_SOFTWARE);	/* Should have aborted. */
23788276dfbSKyle Evans 
23888276dfbSKyle Evans monitor:
23988276dfbSKyle Evans 	while (waitpid(__child, &__status, 0) != __child) {
24088276dfbSKyle Evans 		ATF_REQUIRE_EQ(EINTR, errno);
24188276dfbSKyle Evans 	}
24288276dfbSKyle Evans 
24388276dfbSKyle Evans 	if (!WIFSIGNALED(__status)) {
24488276dfbSKyle Evans 		switch (WEXITSTATUS(__status)) {
24588276dfbSKyle Evans 		case EX_SOFTWARE:
24688276dfbSKyle Evans 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
24788276dfbSKyle Evans 			break;
24888276dfbSKyle Evans 		case EX_OSERR:
24988276dfbSKyle Evans 			atf_tc_fail("setrlimit(2) failed");
25088276dfbSKyle Evans 			break;
25188276dfbSKyle Evans 		default:
25288276dfbSKyle Evans 			atf_tc_fail("child exited with status %d",
25388276dfbSKyle Evans 			    WEXITSTATUS(__status));
25488276dfbSKyle Evans 		}
25588276dfbSKyle Evans 	} else {
25688276dfbSKyle Evans 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
25788276dfbSKyle Evans 	}
25888276dfbSKyle Evans #undef BUF
25988276dfbSKyle Evans 
26088276dfbSKyle Evans }
26188276dfbSKyle Evans 
26288276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_heap_before_end);
ATF_TC_BODY(poll_heap_before_end,tc)26388276dfbSKyle Evans ATF_TC_BODY(poll_heap_before_end, tc)
26488276dfbSKyle Evans {
26588276dfbSKyle Evans #define BUF __stack.__buf
26688276dfbSKyle Evans 	struct {
26788276dfbSKyle Evans 		uint8_t padding_l;
26888276dfbSKyle Evans 		struct pollfd * __buf;
26988276dfbSKyle Evans 		uint8_t padding_r;
27088276dfbSKyle Evans 	} __stack;
27188276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
27288276dfbSKyle Evans 	const size_t __len = 4 - 1;
27388276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
27488276dfbSKyle Evans 
27588276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
27688276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
27788276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
27888276dfbSKyle Evans 	}
27988276dfbSKyle Evans 
28088276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
28188276dfbSKyle Evans #undef BUF
28288276dfbSKyle Evans 
28388276dfbSKyle Evans }
28488276dfbSKyle Evans 
28588276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_heap_end);
ATF_TC_BODY(poll_heap_end,tc)28688276dfbSKyle Evans ATF_TC_BODY(poll_heap_end, tc)
28788276dfbSKyle Evans {
28888276dfbSKyle Evans #define BUF __stack.__buf
28988276dfbSKyle Evans 	struct {
29088276dfbSKyle Evans 		uint8_t padding_l;
29188276dfbSKyle Evans 		struct pollfd * __buf;
29288276dfbSKyle Evans 		uint8_t padding_r;
29388276dfbSKyle Evans 	} __stack;
29488276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
29588276dfbSKyle Evans 	const size_t __len = 4;
29688276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
29788276dfbSKyle Evans 
29888276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
29988276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
30088276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
30188276dfbSKyle Evans 	}
30288276dfbSKyle Evans 
30388276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
30488276dfbSKyle Evans #undef BUF
30588276dfbSKyle Evans 
30688276dfbSKyle Evans }
30788276dfbSKyle Evans 
30888276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(poll_heap_after_end);
ATF_TC_BODY(poll_heap_after_end,tc)30988276dfbSKyle Evans ATF_TC_BODY(poll_heap_after_end, tc)
31088276dfbSKyle Evans {
31188276dfbSKyle Evans #define BUF __stack.__buf
31288276dfbSKyle Evans 	struct {
31388276dfbSKyle Evans 		uint8_t padding_l;
31488276dfbSKyle Evans 		struct pollfd * __buf;
31588276dfbSKyle Evans 		uint8_t padding_r;
31688276dfbSKyle Evans 	} __stack;
31788276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
31888276dfbSKyle Evans 	const size_t __len = 4 + 1;
31988276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
32088276dfbSKyle Evans 	pid_t __child;
32188276dfbSKyle Evans 	int __status;
32288276dfbSKyle Evans 
32388276dfbSKyle Evans 	__child = fork();
32488276dfbSKyle Evans 	ATF_REQUIRE(__child >= 0);
32588276dfbSKyle Evans 	if (__child > 0)
32688276dfbSKyle Evans 		goto monitor;
32788276dfbSKyle Evans 
32888276dfbSKyle Evans 	/* Child */
32988276dfbSKyle Evans 	disable_coredumps();
33088276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
33188276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
33288276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
33388276dfbSKyle Evans 	}
33488276dfbSKyle Evans 
33588276dfbSKyle Evans 	poll(__stack.__buf, __len, 0);
33688276dfbSKyle Evans 	_exit(EX_SOFTWARE);	/* Should have aborted. */
33788276dfbSKyle Evans 
33888276dfbSKyle Evans monitor:
33988276dfbSKyle Evans 	while (waitpid(__child, &__status, 0) != __child) {
34088276dfbSKyle Evans 		ATF_REQUIRE_EQ(EINTR, errno);
34188276dfbSKyle Evans 	}
34288276dfbSKyle Evans 
34388276dfbSKyle Evans 	if (!WIFSIGNALED(__status)) {
34488276dfbSKyle Evans 		switch (WEXITSTATUS(__status)) {
34588276dfbSKyle Evans 		case EX_SOFTWARE:
34688276dfbSKyle Evans 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
34788276dfbSKyle Evans 			break;
34888276dfbSKyle Evans 		case EX_OSERR:
34988276dfbSKyle Evans 			atf_tc_fail("setrlimit(2) failed");
35088276dfbSKyle Evans 			break;
35188276dfbSKyle Evans 		default:
35288276dfbSKyle Evans 			atf_tc_fail("child exited with status %d",
35388276dfbSKyle Evans 			    WEXITSTATUS(__status));
35488276dfbSKyle Evans 		}
35588276dfbSKyle Evans 	} else {
35688276dfbSKyle Evans 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
35788276dfbSKyle Evans 	}
35888276dfbSKyle Evans #undef BUF
35988276dfbSKyle Evans 
36088276dfbSKyle Evans }
36188276dfbSKyle Evans 
36288276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_before_end);
ATF_TC_BODY(ppoll_before_end,tc)36388276dfbSKyle Evans ATF_TC_BODY(ppoll_before_end, tc)
36488276dfbSKyle Evans {
36588276dfbSKyle Evans #define BUF &__stack.__buf
36688276dfbSKyle Evans 	struct {
36788276dfbSKyle Evans 		uint8_t padding_l;
36888276dfbSKyle Evans 		struct pollfd __buf[4];
36988276dfbSKyle Evans 		uint8_t padding_r;
37088276dfbSKyle Evans 	} __stack;
37188276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
37288276dfbSKyle Evans 	const size_t __len = 4 - 1;
37388276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
37488276dfbSKyle Evans 	struct timespec tv = { 0 };
37588276dfbSKyle Evans 
37688276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
37788276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
37888276dfbSKyle Evans 	}
37988276dfbSKyle Evans 
38088276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
38188276dfbSKyle Evans #undef BUF
38288276dfbSKyle Evans 
38388276dfbSKyle Evans }
38488276dfbSKyle Evans 
38588276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_end);
ATF_TC_BODY(ppoll_end,tc)38688276dfbSKyle Evans ATF_TC_BODY(ppoll_end, tc)
38788276dfbSKyle Evans {
38888276dfbSKyle Evans #define BUF &__stack.__buf
38988276dfbSKyle Evans 	struct {
39088276dfbSKyle Evans 		uint8_t padding_l;
39188276dfbSKyle Evans 		struct pollfd __buf[4];
39288276dfbSKyle Evans 		uint8_t padding_r;
39388276dfbSKyle Evans 	} __stack;
39488276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
39588276dfbSKyle Evans 	const size_t __len = 4;
39688276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
39788276dfbSKyle Evans 	struct timespec tv = { 0 };
39888276dfbSKyle Evans 
39988276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
40088276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
40188276dfbSKyle Evans 	}
40288276dfbSKyle Evans 
40388276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
40488276dfbSKyle Evans #undef BUF
40588276dfbSKyle Evans 
40688276dfbSKyle Evans }
40788276dfbSKyle Evans 
40888276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_after_end);
ATF_TC_BODY(ppoll_after_end,tc)40988276dfbSKyle Evans ATF_TC_BODY(ppoll_after_end, tc)
41088276dfbSKyle Evans {
41188276dfbSKyle Evans #define BUF &__stack.__buf
41288276dfbSKyle Evans 	struct {
41388276dfbSKyle Evans 		uint8_t padding_l;
41488276dfbSKyle Evans 		struct pollfd __buf[4];
41588276dfbSKyle Evans 		uint8_t padding_r;
41688276dfbSKyle Evans 	} __stack;
41788276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(__stack.__buf);
41888276dfbSKyle Evans 	const size_t __len = 4 + 1;
41988276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
42088276dfbSKyle Evans 	pid_t __child;
42188276dfbSKyle Evans 	int __status;
42288276dfbSKyle Evans 	struct timespec tv = { 0 };
42388276dfbSKyle Evans 
42488276dfbSKyle Evans 	__child = fork();
42588276dfbSKyle Evans 	ATF_REQUIRE(__child >= 0);
42688276dfbSKyle Evans 	if (__child > 0)
42788276dfbSKyle Evans 		goto monitor;
42888276dfbSKyle Evans 
42988276dfbSKyle Evans 	/* Child */
43088276dfbSKyle Evans 	disable_coredumps();
43188276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
43288276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
43388276dfbSKyle Evans 	}
43488276dfbSKyle Evans 
43588276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
43688276dfbSKyle Evans 	_exit(EX_SOFTWARE);	/* Should have aborted. */
43788276dfbSKyle Evans 
43888276dfbSKyle Evans monitor:
43988276dfbSKyle Evans 	while (waitpid(__child, &__status, 0) != __child) {
44088276dfbSKyle Evans 		ATF_REQUIRE_EQ(EINTR, errno);
44188276dfbSKyle Evans 	}
44288276dfbSKyle Evans 
44388276dfbSKyle Evans 	if (!WIFSIGNALED(__status)) {
44488276dfbSKyle Evans 		switch (WEXITSTATUS(__status)) {
44588276dfbSKyle Evans 		case EX_SOFTWARE:
44688276dfbSKyle Evans 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
44788276dfbSKyle Evans 			break;
44888276dfbSKyle Evans 		case EX_OSERR:
44988276dfbSKyle Evans 			atf_tc_fail("setrlimit(2) failed");
45088276dfbSKyle Evans 			break;
45188276dfbSKyle Evans 		default:
45288276dfbSKyle Evans 			atf_tc_fail("child exited with status %d",
45388276dfbSKyle Evans 			    WEXITSTATUS(__status));
45488276dfbSKyle Evans 		}
45588276dfbSKyle Evans 	} else {
45688276dfbSKyle Evans 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
45788276dfbSKyle Evans 	}
45888276dfbSKyle Evans #undef BUF
45988276dfbSKyle Evans 
46088276dfbSKyle Evans }
46188276dfbSKyle Evans 
46288276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_heap_before_end);
ATF_TC_BODY(ppoll_heap_before_end,tc)46388276dfbSKyle Evans ATF_TC_BODY(ppoll_heap_before_end, tc)
46488276dfbSKyle Evans {
46588276dfbSKyle Evans #define BUF __stack.__buf
46688276dfbSKyle Evans 	struct {
46788276dfbSKyle Evans 		uint8_t padding_l;
46888276dfbSKyle Evans 		struct pollfd * __buf;
46988276dfbSKyle Evans 		uint8_t padding_r;
47088276dfbSKyle Evans 	} __stack;
47188276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
47288276dfbSKyle Evans 	const size_t __len = 4 - 1;
47388276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
47488276dfbSKyle Evans 	struct timespec tv = { 0 };
47588276dfbSKyle Evans 
47688276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
47788276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
47888276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
47988276dfbSKyle Evans 	}
48088276dfbSKyle Evans 
48188276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
48288276dfbSKyle Evans #undef BUF
48388276dfbSKyle Evans 
48488276dfbSKyle Evans }
48588276dfbSKyle Evans 
48688276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_heap_end);
ATF_TC_BODY(ppoll_heap_end,tc)48788276dfbSKyle Evans ATF_TC_BODY(ppoll_heap_end, tc)
48888276dfbSKyle Evans {
48988276dfbSKyle Evans #define BUF __stack.__buf
49088276dfbSKyle Evans 	struct {
49188276dfbSKyle Evans 		uint8_t padding_l;
49288276dfbSKyle Evans 		struct pollfd * __buf;
49388276dfbSKyle Evans 		uint8_t padding_r;
49488276dfbSKyle Evans 	} __stack;
49588276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
49688276dfbSKyle Evans 	const size_t __len = 4;
49788276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
49888276dfbSKyle Evans 	struct timespec tv = { 0 };
49988276dfbSKyle Evans 
50088276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
50188276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
50288276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
50388276dfbSKyle Evans 	}
50488276dfbSKyle Evans 
50588276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
50688276dfbSKyle Evans #undef BUF
50788276dfbSKyle Evans 
50888276dfbSKyle Evans }
50988276dfbSKyle Evans 
51088276dfbSKyle Evans ATF_TC_WITHOUT_HEAD(ppoll_heap_after_end);
ATF_TC_BODY(ppoll_heap_after_end,tc)51188276dfbSKyle Evans ATF_TC_BODY(ppoll_heap_after_end, tc)
51288276dfbSKyle Evans {
51388276dfbSKyle Evans #define BUF __stack.__buf
51488276dfbSKyle Evans 	struct {
51588276dfbSKyle Evans 		uint8_t padding_l;
51688276dfbSKyle Evans 		struct pollfd * __buf;
51788276dfbSKyle Evans 		uint8_t padding_r;
51888276dfbSKyle Evans 	} __stack;
51988276dfbSKyle Evans 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4);
52088276dfbSKyle Evans 	const size_t __len = 4 + 1;
52188276dfbSKyle Evans 	const size_t __idx __unused = __len - 1;
52288276dfbSKyle Evans 	pid_t __child;
52388276dfbSKyle Evans 	int __status;
52488276dfbSKyle Evans 	struct timespec tv = { 0 };
52588276dfbSKyle Evans 
52688276dfbSKyle Evans 	__child = fork();
52788276dfbSKyle Evans 	ATF_REQUIRE(__child >= 0);
52888276dfbSKyle Evans 	if (__child > 0)
52988276dfbSKyle Evans 		goto monitor;
53088276dfbSKyle Evans 
53188276dfbSKyle Evans 	/* Child */
53288276dfbSKyle Evans 	disable_coredumps();
53388276dfbSKyle Evans 	__stack.__buf = malloc(__bufsz);
53488276dfbSKyle Evans 	for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) {
53588276dfbSKyle Evans 		__stack.__buf[i].fd = -1;
53688276dfbSKyle Evans 	}
53788276dfbSKyle Evans 
53888276dfbSKyle Evans 	ppoll(__stack.__buf, __len, &tv, NULL);
53988276dfbSKyle Evans 	_exit(EX_SOFTWARE);	/* Should have aborted. */
54088276dfbSKyle Evans 
54188276dfbSKyle Evans monitor:
54288276dfbSKyle Evans 	while (waitpid(__child, &__status, 0) != __child) {
54388276dfbSKyle Evans 		ATF_REQUIRE_EQ(EINTR, errno);
54488276dfbSKyle Evans 	}
54588276dfbSKyle Evans 
54688276dfbSKyle Evans 	if (!WIFSIGNALED(__status)) {
54788276dfbSKyle Evans 		switch (WEXITSTATUS(__status)) {
54888276dfbSKyle Evans 		case EX_SOFTWARE:
54988276dfbSKyle Evans 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
55088276dfbSKyle Evans 			break;
55188276dfbSKyle Evans 		case EX_OSERR:
55288276dfbSKyle Evans 			atf_tc_fail("setrlimit(2) failed");
55388276dfbSKyle Evans 			break;
55488276dfbSKyle Evans 		default:
55588276dfbSKyle Evans 			atf_tc_fail("child exited with status %d",
55688276dfbSKyle Evans 			    WEXITSTATUS(__status));
55788276dfbSKyle Evans 		}
55888276dfbSKyle Evans 	} else {
55988276dfbSKyle Evans 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
56088276dfbSKyle Evans 	}
56188276dfbSKyle Evans #undef BUF
56288276dfbSKyle Evans 
56388276dfbSKyle Evans }
56488276dfbSKyle Evans 
ATF_TP_ADD_TCS(tp)56588276dfbSKyle Evans ATF_TP_ADD_TCS(tp)
56688276dfbSKyle Evans {
56788276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_before_end);
56888276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_end);
56988276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_after_end);
57088276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_heap_before_end);
57188276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_heap_end);
57288276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, poll_heap_after_end);
57388276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_before_end);
57488276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_end);
57588276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_after_end);
57688276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_heap_before_end);
57788276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_heap_end);
57888276dfbSKyle Evans 	ATF_TP_ADD_TC(tp, ppoll_heap_after_end);
57988276dfbSKyle Evans 	return (atf_no_error());
58088276dfbSKyle Evans }
581