diff options
Diffstat (limited to 'lib/libc/tests/secure')
-rw-r--r-- | lib/libc/tests/secure/Makefile | 39 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_poll_test.c | 617 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_random_test.c | 316 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_select_test.c | 769 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_signal_test.c | 316 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_socket_test.c | 1971 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_stdio_test.c | 1559 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_stdlib_test.c | 610 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_string_test.c | 2271 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_strings_test.c | 615 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_uio_test.c | 917 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_unistd_test.c | 2199 | ||||
-rw-r--r-- | lib/libc/tests/secure/fortify_wchar_test.c | 2124 | ||||
-rwxr-xr-x | lib/libc/tests/secure/generate-fortify-tests.lua | 1581 |
14 files changed, 15904 insertions, 0 deletions
diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile new file mode 100644 index 000000000000..515f8f53a43e --- /dev/null +++ b/lib/libc/tests/secure/Makefile @@ -0,0 +1,39 @@ +.include <bsd.own.mk> + +TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} + +# sys/ headers +FORTIFY_TCATS+= random +FORTIFY_TCATS+= select +FORTIFY_TCATS+= socket +FORTIFY_TCATS+= uio + +# non-sys/ headers +FORTIFY_TCATS+= poll +FORTIFY_TCATS+= signal +FORTIFY_TCATS+= stdlib +FORTIFY_TCATS+= stdio +FORTIFY_TCATS+= string +FORTIFY_TCATS+= strings +FORTIFY_TCATS+= unistd +FORTIFY_TCATS+= wchar + +# Manually run after updating the test generator. +lint-generator: .PHONY + @if ! which luacheck>/dev/null; then \ + 1>&2 echo "devel/lua-luacheck is required to regenerate and lint these tests"; \ + exit 1; \ + fi + luacheck ${.CURDIR}/generate-fortify-tests.lua + +generate-tests: .PHONY lint-generator +.for tcat in ${FORTIFY_TCATS} +ATF_TESTS_C+= fortify_${tcat}_test + +.ORDER: lint-generator generate-tests-${tcat} +generate-tests: generate-tests-${tcat} +generate-tests-${tcat}: .PHONY + ${.CURDIR}/generate-fortify-tests.lua ${tcat} > ${.CURDIR}/fortify_${tcat}_test.c +.endfor + +.include <bsd.test.mk> diff --git a/lib/libc/tests/secure/fortify_poll_test.c b/lib/libc/tests/secure/fortify_poll_test.c new file mode 100644 index 000000000000..3810c16c122f --- /dev/null +++ b/lib/libc/tests/secure/fortify_poll_test.c @@ -0,0 +1,617 @@ +/* @generated by `generate-fortify-tests.lua "poll"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(poll_before_end); +ATF_TC_HEAD(poll_before_end, tc) +{ +} +ATF_TC_BODY(poll_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(poll_end); +ATF_TC_HEAD(poll_end, tc) +{ +} +ATF_TC_BODY(poll_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(poll_after_end); +ATF_TC_HEAD(poll_after_end, tc) +{ +} +ATF_TC_BODY(poll_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(poll_heap_before_end); +ATF_TC_HEAD(poll_heap_before_end, tc) +{ +} +ATF_TC_BODY(poll_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(poll_heap_end); +ATF_TC_HEAD(poll_heap_end, tc) +{ +} +ATF_TC_BODY(poll_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(poll_heap_after_end); +ATF_TC_HEAD(poll_heap_after_end, tc) +{ +} +ATF_TC_BODY(poll_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + poll(__stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(ppoll_before_end); +ATF_TC_HEAD(ppoll_before_end, tc) +{ +} +ATF_TC_BODY(ppoll_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + struct timespec tv = { 0 }; + + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); +#undef BUF + +} + +ATF_TC(ppoll_end); +ATF_TC_HEAD(ppoll_end, tc) +{ +} +ATF_TC_BODY(ppoll_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + struct timespec tv = { 0 }; + + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); +#undef BUF + +} + +ATF_TC(ppoll_after_end); +ATF_TC_HEAD(ppoll_after_end, tc) +{ +} +ATF_TC_BODY(ppoll_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct pollfd __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + struct timespec tv = { 0 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(ppoll_heap_before_end); +ATF_TC_HEAD(ppoll_heap_before_end, tc) +{ +} +ATF_TC_BODY(ppoll_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + struct timespec tv = { 0 }; + + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); +#undef BUF + +} + +ATF_TC(ppoll_heap_end); +ATF_TC_HEAD(ppoll_heap_end, tc) +{ +} +ATF_TC_BODY(ppoll_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + struct timespec tv = { 0 }; + + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); +#undef BUF + +} + +ATF_TC(ppoll_heap_after_end); +ATF_TC_HEAD(ppoll_heap_after_end, tc) +{ +} +ATF_TC_BODY(ppoll_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct pollfd * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + struct timespec tv = { 0 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } + + ppoll(__stack.__buf, __len, &tv, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, poll_before_end); + ATF_TP_ADD_TC(tp, poll_end); + ATF_TP_ADD_TC(tp, poll_after_end); + ATF_TP_ADD_TC(tp, poll_heap_before_end); + ATF_TP_ADD_TC(tp, poll_heap_end); + ATF_TP_ADD_TC(tp, poll_heap_after_end); + ATF_TP_ADD_TC(tp, ppoll_before_end); + ATF_TP_ADD_TC(tp, ppoll_end); + ATF_TP_ADD_TC(tp, ppoll_after_end); + ATF_TP_ADD_TC(tp, ppoll_heap_before_end); + ATF_TP_ADD_TC(tp, ppoll_heap_end); + ATF_TP_ADD_TC(tp, ppoll_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_random_test.c b/lib/libc/tests/secure/fortify_random_test.c new file mode 100644 index 000000000000..2f47c981b5ae --- /dev/null +++ b/lib/libc/tests/secure/fortify_random_test.c @@ -0,0 +1,316 @@ +/* @generated by `generate-fortify-tests.lua "random"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(getrandom_before_end); +ATF_TC_HEAD(getrandom_before_end, tc) +{ +} +ATF_TC_BODY(getrandom_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getrandom(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(getrandom_end); +ATF_TC_HEAD(getrandom_end, tc) +{ +} +ATF_TC_BODY(getrandom_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getrandom(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(getrandom_heap_before_end); +ATF_TC_HEAD(getrandom_heap_before_end, tc) +{ +} +ATF_TC_BODY(getrandom_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getrandom(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(getrandom_heap_end); +ATF_TC_HEAD(getrandom_heap_end, tc) +{ +} +ATF_TC_BODY(getrandom_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getrandom(__stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(getrandom_heap_after_end); +ATF_TC_HEAD(getrandom_heap_after_end, tc) +{ +} +ATF_TC_BODY(getrandom_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getrandom(__stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getrandom_before_end); + ATF_TP_ADD_TC(tp, getrandom_end); + ATF_TP_ADD_TC(tp, getrandom_heap_before_end); + ATF_TP_ADD_TC(tp, getrandom_heap_end); + ATF_TP_ADD_TC(tp, getrandom_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_select_test.c b/lib/libc/tests/secure/fortify_select_test.c new file mode 100644 index 000000000000..5ee97a352e2e --- /dev/null +++ b/lib/libc/tests/secure/fortify_select_test.c @@ -0,0 +1,769 @@ +/* @generated by `generate-fortify-tests.lua "select"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(FD_SET_before_end); +ATF_TC_HEAD(FD_SET_before_end, tc) +{ +} +ATF_TC_BODY(FD_SET_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_SET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_SET_end); +ATF_TC_HEAD(FD_SET_end, tc) +{ +} +ATF_TC_BODY(FD_SET_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_SET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_SET_after_end); +ATF_TC_HEAD(FD_SET_after_end, tc) +{ +} +ATF_TC_BODY(FD_SET_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_SET(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(FD_SET_heap_before_end); +ATF_TC_HEAD(FD_SET_heap_before_end, tc) +{ +} +ATF_TC_BODY(FD_SET_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_SET_heap_end); +ATF_TC_HEAD(FD_SET_heap_end, tc) +{ +} +ATF_TC_BODY(FD_SET_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_SET_heap_after_end); +ATF_TC_HEAD(FD_SET_heap_after_end, tc) +{ +} +ATF_TC_BODY(FD_SET_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(FD_CLR_before_end); +ATF_TC_HEAD(FD_CLR_before_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_CLR(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_CLR_end); +ATF_TC_HEAD(FD_CLR_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_CLR(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_CLR_after_end); +ATF_TC_HEAD(FD_CLR_after_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_CLR(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(FD_CLR_heap_before_end); +ATF_TC_HEAD(FD_CLR_heap_before_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_CLR_heap_end); +ATF_TC_HEAD(FD_CLR_heap_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_CLR_heap_after_end); +ATF_TC_HEAD(FD_CLR_heap_after_end, tc) +{ +} +ATF_TC_BODY(FD_CLR_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(FD_ISSET_before_end); +ATF_TC_HEAD(FD_ISSET_before_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_ISSET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_ISSET_end); +ATF_TC_HEAD(FD_ISSET_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_ISSET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC(FD_ISSET_after_end); +ATF_TC_HEAD(FD_ISSET_after_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_ISSET(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(FD_ISSET_heap_before_end); +ATF_TC_HEAD(FD_ISSET_heap_before_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_ISSET_heap_end); +ATF_TC_HEAD(FD_ISSET_heap_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC(FD_ISSET_heap_after_end); +ATF_TC_HEAD(FD_ISSET_heap_after_end, tc) +{ +} +ATF_TC_BODY(FD_ISSET_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, FD_SET_before_end); + ATF_TP_ADD_TC(tp, FD_SET_end); + ATF_TP_ADD_TC(tp, FD_SET_after_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_before_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_after_end); + ATF_TP_ADD_TC(tp, FD_CLR_before_end); + ATF_TP_ADD_TC(tp, FD_CLR_end); + ATF_TP_ADD_TC(tp, FD_CLR_after_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_before_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_after_end); + ATF_TP_ADD_TC(tp, FD_ISSET_before_end); + ATF_TP_ADD_TC(tp, FD_ISSET_end); + ATF_TP_ADD_TC(tp, FD_ISSET_after_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_before_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_signal_test.c b/lib/libc/tests/secure/fortify_signal_test.c new file mode 100644 index 000000000000..03cfb9a9a13a --- /dev/null +++ b/lib/libc/tests/secure/fortify_signal_test.c @@ -0,0 +1,316 @@ +/* @generated by `generate-fortify-tests.lua "signal"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(sig2str_before_end); +ATF_TC_HEAD(sig2str_before_end, tc) +{ +} +ATF_TC_BODY(sig2str_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[SIG2STR_MAX + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = SIG2STR_MAX + 1; + const size_t __idx __unused = __len - 1; + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_end); +ATF_TC_HEAD(sig2str_end, tc) +{ +} +ATF_TC_BODY(sig2str_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[SIG2STR_MAX]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = SIG2STR_MAX; + const size_t __idx __unused = __len - 1; + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_before_end); +ATF_TC_HEAD(sig2str_heap_before_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX + 1); + const size_t __len = SIG2STR_MAX + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_end); +ATF_TC_HEAD(sig2str_heap_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX); + const size_t __len = SIG2STR_MAX; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_after_end); +ATF_TC_HEAD(sig2str_heap_after_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX - 1); + const size_t __len = SIG2STR_MAX - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, sig2str_before_end); + ATF_TP_ADD_TC(tp, sig2str_end); + ATF_TP_ADD_TC(tp, sig2str_heap_before_end); + ATF_TP_ADD_TC(tp, sig2str_heap_end); + ATF_TP_ADD_TC(tp, sig2str_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_socket_test.c b/lib/libc/tests/secure/fortify_socket_test.c new file mode 100644 index 000000000000..3d2dc86f4e1c --- /dev/null +++ b/lib/libc/tests/secure/fortify_socket_test.c @@ -0,0 +1,1971 @@ +/* @generated by `generate-fortify-tests.lua "socket"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(getpeername_before_end); +ATF_TC_HEAD(getpeername_before_end, tc) +{ +} +ATF_TC_BODY(getpeername_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + new_socket(sock); + socklen = __len; + + getpeername(sock[0], &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getpeername_end); +ATF_TC_HEAD(getpeername_end, tc) +{ +} +ATF_TC_BODY(getpeername_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + new_socket(sock); + socklen = __len; + + getpeername(sock[0], &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getpeername_heap_before_end); +ATF_TC_HEAD(getpeername_heap_before_end, tc) +{ +} +ATF_TC_BODY(getpeername_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getpeername(sock[0], __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getpeername_heap_end); +ATF_TC_HEAD(getpeername_heap_end, tc) +{ +} +ATF_TC_BODY(getpeername_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getpeername(sock[0], __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getpeername_heap_after_end); +ATF_TC_HEAD(getpeername_heap_after_end, tc) +{ +} +ATF_TC_BODY(getpeername_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getpeername(sock[0], __stack.__buf, &socklen); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getsockname_before_end); +ATF_TC_HEAD(getsockname_before_end, tc) +{ +} +ATF_TC_BODY(getsockname_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + new_socket(sock); + socklen = __len; + + getsockname(sock[0], &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getsockname_end); +ATF_TC_HEAD(getsockname_end, tc) +{ +} +ATF_TC_BODY(getsockname_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + new_socket(sock); + socklen = __len; + + getsockname(sock[0], &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getsockname_heap_before_end); +ATF_TC_HEAD(getsockname_heap_before_end, tc) +{ +} +ATF_TC_BODY(getsockname_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getsockname(sock[0], __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getsockname_heap_end); +ATF_TC_HEAD(getsockname_heap_end, tc) +{ +} +ATF_TC_BODY(getsockname_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getsockname(sock[0], __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(getsockname_heap_after_end); +ATF_TC_HEAD(getsockname_heap_after_end, tc) +{ +} +ATF_TC_BODY(getsockname_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + socklen_t socklen; + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + getsockname(sock[0], __stack.__buf, &socklen); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recv_before_end); +ATF_TC_HEAD(recv_before_end, tc) +{ +} +ATF_TC_BODY(recv_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + new_socket(sock); + + recv(sock[0], __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(recv_end); +ATF_TC_HEAD(recv_end, tc) +{ +} +ATF_TC_BODY(recv_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + new_socket(sock); + + recv(sock[0], __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(recv_heap_before_end); +ATF_TC_HEAD(recv_heap_before_end, tc) +{ +} +ATF_TC_BODY(recv_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recv(sock[0], __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(recv_heap_end); +ATF_TC_HEAD(recv_heap_end, tc) +{ +} +ATF_TC_BODY(recv_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recv(sock[0], __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(recv_heap_after_end); +ATF_TC_HEAD(recv_heap_after_end, tc) +{ +} +ATF_TC_BODY(recv_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recv(sock[0], __stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvfrom_before_end); +ATF_TC_HEAD(recvfrom_before_end, tc) +{ +} +ATF_TC_BODY(recvfrom_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + new_socket(sock); + + recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL); +#undef BUF + +} + +ATF_TC(recvfrom_end); +ATF_TC_HEAD(recvfrom_end, tc) +{ +} +ATF_TC_BODY(recvfrom_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + new_socket(sock); + + recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL); +#undef BUF + +} + +ATF_TC(recvfrom_heap_before_end); +ATF_TC_HEAD(recvfrom_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvfrom_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL); +#undef BUF + +} + +ATF_TC(recvfrom_heap_end); +ATF_TC_HEAD(recvfrom_heap_end, tc) +{ +} +ATF_TC_BODY(recvfrom_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL); +#undef BUF + +} + +ATF_TC(recvfrom_heap_after_end); +ATF_TC_HEAD(recvfrom_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvfrom_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + new_socket(sock); + + recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvfrom_sockaddr_before_end); +ATF_TC_HEAD(recvfrom_sockaddr_before_end, tc) +{ +} +ATF_TC_BODY(recvfrom_sockaddr_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + char data[16]; + socklen_t socklen; + + new_socket(sock); + socklen = __len; + + recvfrom(sock[0], data, sizeof(data), 0, &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(recvfrom_sockaddr_end); +ATF_TC_HEAD(recvfrom_sockaddr_end, tc) +{ +} +ATF_TC_BODY(recvfrom_sockaddr_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + char data[16]; + socklen_t socklen; + + new_socket(sock); + socklen = __len; + + recvfrom(sock[0], data, sizeof(data), 0, &__stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(recvfrom_sockaddr_heap_before_end); +ATF_TC_HEAD(recvfrom_sockaddr_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvfrom_sockaddr_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + char data[16]; + socklen_t socklen; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(recvfrom_sockaddr_heap_end); +ATF_TC_HEAD(recvfrom_sockaddr_heap_end, tc) +{ +} +ATF_TC_BODY(recvfrom_sockaddr_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + char data[16]; + socklen_t socklen; + + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen); +#undef BUF + +} + +ATF_TC(recvfrom_sockaddr_heap_after_end); +ATF_TC_HEAD(recvfrom_sockaddr_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvfrom_sockaddr_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + char data[16]; + socklen_t socklen; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + new_socket(sock); + socklen = __len; + + recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmsg_msg_name_before_end); +ATF_TC_HEAD(recvmsg_msg_name_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_name_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_name_end); +ATF_TC_HEAD(recvmsg_msg_name_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_name_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct sockaddr __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_name_heap_before_end); +ATF_TC_HEAD(recvmsg_msg_name_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_name_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_name_heap_end); +ATF_TC_HEAD(recvmsg_msg_name_heap_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_name_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_name_heap_after_end); +ATF_TC_HEAD(recvmsg_msg_name_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_name_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct sockaddr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = sizeof(struct sockaddr) + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; + + recvmsg(sock[0], &msg, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmsg_msg_iov_before_end); +ATF_TC_HEAD(recvmsg_msg_iov_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_iov_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + struct iovec iov[2]; + + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_iov_end); +ATF_TC_HEAD(recvmsg_msg_iov_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_iov_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + struct iovec iov[2]; + + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_iov_heap_before_end); +ATF_TC_HEAD(recvmsg_msg_iov_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_iov_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + struct iovec iov[2]; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_iov_heap_end); +ATF_TC_HEAD(recvmsg_msg_iov_heap_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_iov_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + struct iovec iov[2]; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_iov_heap_after_end); +ATF_TC_HEAD(recvmsg_msg_iov_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_iov_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + struct msghdr msg; + struct iovec iov[2]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); + + recvmsg(sock[0], &msg, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmsg_msg_control_before_end); +ATF_TC_HEAD(recvmsg_msg_control_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_control_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[CMSG_SPACE(sizeof(int))]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = CMSG_SPACE(sizeof(int)) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_control_end); +ATF_TC_HEAD(recvmsg_msg_control_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_control_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[CMSG_SPACE(sizeof(int))]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = CMSG_SPACE(sizeof(int)); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_control_heap_before_end); +ATF_TC_HEAD(recvmsg_msg_control_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_control_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int))); + const size_t __len = CMSG_SPACE(sizeof(int)) - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_control_heap_end); +ATF_TC_HEAD(recvmsg_msg_control_heap_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_control_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int))); + const size_t __len = CMSG_SPACE(sizeof(int)); + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; + + recvmsg(sock[0], &msg, 0); +#undef BUF + +} + +ATF_TC(recvmsg_msg_control_heap_after_end); +ATF_TC_HEAD(recvmsg_msg_control_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvmsg_msg_control_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int))); + const size_t __len = CMSG_SPACE(sizeof(int)) + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + struct msghdr msg; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; + + recvmsg(sock[0], &msg, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_before_end); +ATF_TC_HEAD(recvmmsg_msgvec_before_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_end); +ATF_TC_HEAD(recvmmsg_msgvec_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_after_end); +ATF_TC_HEAD(recvmmsg_msgvec_after_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_heap_before_end); +ATF_TC_HEAD(recvmmsg_msgvec_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_heap_end); +ATF_TC_HEAD(recvmmsg_msgvec_heap_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + + __stack.__buf = malloc(__bufsz); + + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msgvec_heap_after_end); +ATF_TC_HEAD(recvmmsg_msgvec_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msgvec_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct mmsghdr * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + recvmmsg(sock[0], __stack.__buf, __len, 0, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(recvmmsg_msghdr_before_end); +ATF_TC_HEAD(recvmmsg_msghdr_before_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msghdr_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct mmsghdr msgvec[2]; + + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; + + recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msghdr_end); +ATF_TC_HEAD(recvmmsg_msghdr_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msghdr_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct mmsghdr msgvec[2]; + + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; + + recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msghdr_heap_before_end); +ATF_TC_HEAD(recvmmsg_msghdr_heap_before_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msghdr_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct mmsghdr msgvec[2]; + + __stack.__buf = malloc(__bufsz); + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; + + recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msghdr_heap_end); +ATF_TC_HEAD(recvmmsg_msghdr_heap_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msghdr_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int sock[2] = { -1, -1 }; + struct mmsghdr msgvec[2]; + + __stack.__buf = malloc(__bufsz); + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; + + recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL); +#undef BUF + +} + +ATF_TC(recvmmsg_msghdr_heap_after_end); +ATF_TC_HEAD(recvmmsg_msghdr_heap_after_end, tc) +{ +} +ATF_TC_BODY(recvmmsg_msghdr_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int sock[2] = { -1, -1 }; + struct mmsghdr msgvec[2]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; + + recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getpeername_before_end); + ATF_TP_ADD_TC(tp, getpeername_end); + ATF_TP_ADD_TC(tp, getpeername_heap_before_end); + ATF_TP_ADD_TC(tp, getpeername_heap_end); + ATF_TP_ADD_TC(tp, getpeername_heap_after_end); + ATF_TP_ADD_TC(tp, getsockname_before_end); + ATF_TP_ADD_TC(tp, getsockname_end); + ATF_TP_ADD_TC(tp, getsockname_heap_before_end); + ATF_TP_ADD_TC(tp, getsockname_heap_end); + ATF_TP_ADD_TC(tp, getsockname_heap_after_end); + ATF_TP_ADD_TC(tp, recv_before_end); + ATF_TP_ADD_TC(tp, recv_end); + ATF_TP_ADD_TC(tp, recv_heap_before_end); + ATF_TP_ADD_TC(tp, recv_heap_end); + ATF_TP_ADD_TC(tp, recv_heap_after_end); + ATF_TP_ADD_TC(tp, recvfrom_before_end); + ATF_TP_ADD_TC(tp, recvfrom_end); + ATF_TP_ADD_TC(tp, recvfrom_heap_before_end); + ATF_TP_ADD_TC(tp, recvfrom_heap_end); + ATF_TP_ADD_TC(tp, recvfrom_heap_after_end); + ATF_TP_ADD_TC(tp, recvfrom_sockaddr_before_end); + ATF_TP_ADD_TC(tp, recvfrom_sockaddr_end); + ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_before_end); + ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_end); + ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_after_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_name_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_name_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_after_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_iov_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_iov_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_after_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_control_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_control_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_before_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_end); + ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_after_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_before_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_after_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_before_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_end); + ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_after_end); + ATF_TP_ADD_TC(tp, recvmmsg_msghdr_before_end); + ATF_TP_ADD_TC(tp, recvmmsg_msghdr_end); + ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_before_end); + ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_end); + ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c new file mode 100644 index 000000000000..17842393a740 --- /dev/null +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -0,0 +1,1559 @@ +/* @generated by `generate-fortify-tests.lua "stdio"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(ctermid_before_end); +ATF_TC_HEAD(ctermid_before_end, tc) +{ +} +ATF_TC_BODY(ctermid_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_end); +ATF_TC_HEAD(ctermid_end, tc) +{ +} +ATF_TC_BODY(ctermid_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_heap_before_end); +ATF_TC_HEAD(ctermid_heap_before_end, tc) +{ +} +ATF_TC_BODY(ctermid_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid + 1); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_heap_end); +ATF_TC_HEAD(ctermid_heap_end, tc) +{ +} +ATF_TC_BODY(ctermid_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_heap_after_end); +ATF_TC_HEAD(ctermid_heap_after_end, tc) +{ +} +ATF_TC_BODY(ctermid_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid - 1); + const size_t __len = L_ctermid - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(ctermid_r_before_end); +ATF_TC_HEAD(ctermid_r_before_end, tc) +{ +} +ATF_TC_BODY(ctermid_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_r_end); +ATF_TC_HEAD(ctermid_r_end, tc) +{ +} +ATF_TC_BODY(ctermid_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_r_heap_before_end); +ATF_TC_HEAD(ctermid_r_heap_before_end, tc) +{ +} +ATF_TC_BODY(ctermid_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid + 1); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_r_heap_end); +ATF_TC_HEAD(ctermid_r_heap_end, tc) +{ +} +ATF_TC_BODY(ctermid_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC(ctermid_r_heap_after_end); +ATF_TC_HEAD(ctermid_r_heap_after_end, tc) +{ +} +ATF_TC_BODY(ctermid_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid - 1); + const size_t __len = L_ctermid - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(fread_before_end); +ATF_TC_HEAD(fread_before_end, tc) +{ +} +ATF_TC_BODY(fread_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_end); +ATF_TC_HEAD(fread_end, tc) +{ +} +ATF_TC_BODY(fread_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_heap_before_end); +ATF_TC_HEAD(fread_heap_before_end, tc) +{ +} +ATF_TC_BODY(fread_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_heap_end); +ATF_TC_HEAD(fread_heap_end, tc) +{ +} +ATF_TC_BODY(fread_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_heap_after_end); +ATF_TC_HEAD(fread_heap_after_end, tc) +{ +} +ATF_TC_BODY(fread_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(fread_unlocked_before_end); +ATF_TC_HEAD(fread_unlocked_before_end, tc) +{ +} +ATF_TC_BODY(fread_unlocked_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_unlocked_end); +ATF_TC_HEAD(fread_unlocked_end, tc) +{ +} +ATF_TC_BODY(fread_unlocked_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_unlocked_heap_before_end); +ATF_TC_HEAD(fread_unlocked_heap_before_end, tc) +{ +} +ATF_TC_BODY(fread_unlocked_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_unlocked_heap_end); +ATF_TC_HEAD(fread_unlocked_heap_end, tc) +{ +} +ATF_TC_BODY(fread_unlocked_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC(fread_unlocked_heap_after_end); +ATF_TC_HEAD(fread_unlocked_heap_after_end, tc) +{ +} +ATF_TC_BODY(fread_unlocked_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(gets_s_before_end); +ATF_TC_HEAD(gets_s_before_end, tc) +{ +} +ATF_TC_BODY(gets_s_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gets_s_end); +ATF_TC_HEAD(gets_s_end, tc) +{ +} +ATF_TC_BODY(gets_s_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gets_s_heap_before_end); +ATF_TC_HEAD(gets_s_heap_before_end, tc) +{ +} +ATF_TC_BODY(gets_s_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gets_s_heap_end); +ATF_TC_HEAD(gets_s_heap_end, tc) +{ +} +ATF_TC_BODY(gets_s_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gets_s_heap_after_end); +ATF_TC_HEAD(gets_s_heap_after_end, tc) +{ +} +ATF_TC_BODY(gets_s_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + gets_s(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(sprintf_before_end); +ATF_TC_HEAD(sprintf_before_end, tc) +{ +} +ATF_TC_BODY(sprintf_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(sprintf_end); +ATF_TC_HEAD(sprintf_end, tc) +{ +} +ATF_TC_BODY(sprintf_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(sprintf_heap_before_end); +ATF_TC_HEAD(sprintf_heap_before_end, tc) +{ +} +ATF_TC_BODY(sprintf_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(sprintf_heap_end); +ATF_TC_HEAD(sprintf_heap_end, tc) +{ +} +ATF_TC_BODY(sprintf_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(sprintf_heap_after_end); +ATF_TC_HEAD(sprintf_heap_after_end, tc) +{ +} +ATF_TC_BODY(sprintf_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char srcvar[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(snprintf_before_end); +ATF_TC_HEAD(snprintf_before_end, tc) +{ +} +ATF_TC_BODY(snprintf_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(snprintf_end); +ATF_TC_HEAD(snprintf_end, tc) +{ +} +ATF_TC_BODY(snprintf_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(snprintf_heap_before_end); +ATF_TC_HEAD(snprintf_heap_before_end, tc) +{ +} +ATF_TC_BODY(snprintf_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(snprintf_heap_end); +ATF_TC_HEAD(snprintf_heap_end, tc) +{ +} +ATF_TC_BODY(snprintf_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char srcvar[__len + 10]; + + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); +#undef BUF + +} + +ATF_TC(snprintf_heap_after_end); +ATF_TC_HEAD(snprintf_heap_after_end, tc) +{ +} +ATF_TC_BODY(snprintf_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char srcvar[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; + + snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(tmpnam_before_end); +ATF_TC_HEAD(tmpnam_before_end, tc) +{ +} +ATF_TC_BODY(tmpnam_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_tmpnam + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_tmpnam + 1; + const size_t __idx __unused = __len - 1; + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC(tmpnam_end); +ATF_TC_HEAD(tmpnam_end, tc) +{ +} +ATF_TC_BODY(tmpnam_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_tmpnam]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_tmpnam; + const size_t __idx __unused = __len - 1; + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC(tmpnam_heap_before_end); +ATF_TC_HEAD(tmpnam_heap_before_end, tc) +{ +} +ATF_TC_BODY(tmpnam_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam + 1); + const size_t __len = L_tmpnam + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC(tmpnam_heap_end); +ATF_TC_HEAD(tmpnam_heap_end, tc) +{ +} +ATF_TC_BODY(tmpnam_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam); + const size_t __len = L_tmpnam; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC(tmpnam_heap_after_end); +ATF_TC_HEAD(tmpnam_heap_after_end, tc) +{ +} +ATF_TC_BODY(tmpnam_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam - 1); + const size_t __len = L_tmpnam - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(fgets_before_end); +ATF_TC_HEAD(fgets_before_end, tc) +{ +} +ATF_TC_BODY(fgets_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + FILE *fp; + + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC(fgets_end); +ATF_TC_HEAD(fgets_end, tc) +{ +} +ATF_TC_BODY(fgets_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + FILE *fp; + + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC(fgets_heap_before_end); +ATF_TC_HEAD(fgets_heap_before_end, tc) +{ +} +ATF_TC_BODY(fgets_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + FILE *fp; + + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC(fgets_heap_end); +ATF_TC_HEAD(fgets_heap_end, tc) +{ +} +ATF_TC_BODY(fgets_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + FILE *fp; + + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC(fgets_heap_after_end); +ATF_TC_HEAD(fgets_heap_after_end, tc) +{ +} +ATF_TC_BODY(fgets_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + FILE *fp; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, ctermid_before_end); + ATF_TP_ADD_TC(tp, ctermid_end); + ATF_TP_ADD_TC(tp, ctermid_heap_before_end); + ATF_TP_ADD_TC(tp, ctermid_heap_end); + ATF_TP_ADD_TC(tp, ctermid_heap_after_end); + ATF_TP_ADD_TC(tp, ctermid_r_before_end); + ATF_TP_ADD_TC(tp, ctermid_r_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_before_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_after_end); + ATF_TP_ADD_TC(tp, fread_before_end); + ATF_TP_ADD_TC(tp, fread_end); + ATF_TP_ADD_TC(tp, fread_heap_before_end); + ATF_TP_ADD_TC(tp, fread_heap_end); + ATF_TP_ADD_TC(tp, fread_heap_after_end); + ATF_TP_ADD_TC(tp, fread_unlocked_before_end); + ATF_TP_ADD_TC(tp, fread_unlocked_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_before_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_after_end); + ATF_TP_ADD_TC(tp, gets_s_before_end); + ATF_TP_ADD_TC(tp, gets_s_end); + ATF_TP_ADD_TC(tp, gets_s_heap_before_end); + ATF_TP_ADD_TC(tp, gets_s_heap_end); + ATF_TP_ADD_TC(tp, gets_s_heap_after_end); + ATF_TP_ADD_TC(tp, sprintf_before_end); + ATF_TP_ADD_TC(tp, sprintf_end); + ATF_TP_ADD_TC(tp, sprintf_heap_before_end); + ATF_TP_ADD_TC(tp, sprintf_heap_end); + ATF_TP_ADD_TC(tp, sprintf_heap_after_end); + ATF_TP_ADD_TC(tp, snprintf_before_end); + ATF_TP_ADD_TC(tp, snprintf_end); + ATF_TP_ADD_TC(tp, snprintf_heap_before_end); + ATF_TP_ADD_TC(tp, snprintf_heap_end); + ATF_TP_ADD_TC(tp, snprintf_heap_after_end); + ATF_TP_ADD_TC(tp, tmpnam_before_end); + ATF_TP_ADD_TC(tp, tmpnam_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_before_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_after_end); + ATF_TP_ADD_TC(tp, fgets_before_end); + ATF_TP_ADD_TC(tp, fgets_end); + ATF_TP_ADD_TC(tp, fgets_heap_before_end); + ATF_TP_ADD_TC(tp, fgets_heap_end); + ATF_TP_ADD_TC(tp, fgets_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_stdlib_test.c b/lib/libc/tests/secure/fortify_stdlib_test.c new file mode 100644 index 000000000000..d0b1af78da86 --- /dev/null +++ b/lib/libc/tests/secure/fortify_stdlib_test.c @@ -0,0 +1,610 @@ +/* @generated by `generate-fortify-tests.lua "stdlib"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(arc4random_buf_before_end); +ATF_TC_HEAD(arc4random_buf_before_end, tc) +{ +} +ATF_TC_BODY(arc4random_buf_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + arc4random_buf(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(arc4random_buf_end); +ATF_TC_HEAD(arc4random_buf_end, tc) +{ +} +ATF_TC_BODY(arc4random_buf_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + arc4random_buf(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(arc4random_buf_heap_before_end); +ATF_TC_HEAD(arc4random_buf_heap_before_end, tc) +{ +} +ATF_TC_BODY(arc4random_buf_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + arc4random_buf(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(arc4random_buf_heap_end); +ATF_TC_HEAD(arc4random_buf_heap_end, tc) +{ +} +ATF_TC_BODY(arc4random_buf_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + arc4random_buf(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(arc4random_buf_heap_after_end); +ATF_TC_HEAD(arc4random_buf_heap_after_end, tc) +{ +} +ATF_TC_BODY(arc4random_buf_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + arc4random_buf(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getenv_r_before_end); +ATF_TC_HEAD(getenv_r_before_end, tc) +{ +} +ATF_TC_BODY(getenv_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_end); +ATF_TC_HEAD(getenv_r_end, tc) +{ +} +ATF_TC_BODY(getenv_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_before_end); +ATF_TC_HEAD(getenv_r_heap_before_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_end); +ATF_TC_HEAD(getenv_r_heap_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_after_end); +ATF_TC_HEAD(getenv_r_heap_after_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(realpath_before_end); +ATF_TC_HEAD(realpath_before_end, tc) +{ +} +ATF_TC_BODY(realpath_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[PATH_MAX + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = PATH_MAX + 1; + const size_t __idx __unused = __len - 1; + + realpath(".", __stack.__buf); +#undef BUF + +} + +ATF_TC(realpath_end); +ATF_TC_HEAD(realpath_end, tc) +{ +} +ATF_TC_BODY(realpath_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[PATH_MAX]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = PATH_MAX; + const size_t __idx __unused = __len - 1; + + realpath(".", __stack.__buf); +#undef BUF + +} + +ATF_TC(realpath_heap_before_end); +ATF_TC_HEAD(realpath_heap_before_end, tc) +{ +} +ATF_TC_BODY(realpath_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX + 1); + const size_t __len = PATH_MAX + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + realpath(".", __stack.__buf); +#undef BUF + +} + +ATF_TC(realpath_heap_end); +ATF_TC_HEAD(realpath_heap_end, tc) +{ +} +ATF_TC_BODY(realpath_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX); + const size_t __len = PATH_MAX; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + realpath(".", __stack.__buf); +#undef BUF + +} + +ATF_TC(realpath_heap_after_end); +ATF_TC_HEAD(realpath_heap_after_end, tc) +{ +} +ATF_TC_BODY(realpath_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX - 1); + const size_t __len = PATH_MAX - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + realpath(".", __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, arc4random_buf_before_end); + ATF_TP_ADD_TC(tp, arc4random_buf_end); + ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end); + ATF_TP_ADD_TC(tp, arc4random_buf_heap_end); + ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end); + ATF_TP_ADD_TC(tp, getenv_r_before_end); + ATF_TP_ADD_TC(tp, getenv_r_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_before_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_after_end); + ATF_TP_ADD_TC(tp, realpath_before_end); + ATF_TP_ADD_TC(tp, realpath_end); + ATF_TP_ADD_TC(tp, realpath_heap_before_end); + ATF_TP_ADD_TC(tp, realpath_heap_end); + ATF_TP_ADD_TC(tp, realpath_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c new file mode 100644 index 000000000000..cfea261ff66f --- /dev/null +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -0,0 +1,2271 @@ +/* @generated by `generate-fortify-tests.lua "string"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(memcpy_before_end); +ATF_TC_HEAD(memcpy_before_end, tc) +{ +} +ATF_TC_BODY(memcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + memcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memcpy_end); +ATF_TC_HEAD(memcpy_end, tc) +{ +} +ATF_TC_BODY(memcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + memcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memcpy_heap_before_end); +ATF_TC_HEAD(memcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(memcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + memcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memcpy_heap_end); +ATF_TC_HEAD(memcpy_heap_end, tc) +{ +} +ATF_TC_BODY(memcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + memcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memcpy_heap_after_end); +ATF_TC_HEAD(memcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(memcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + memcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(mempcpy_before_end); +ATF_TC_HEAD(mempcpy_before_end, tc) +{ +} +ATF_TC_BODY(mempcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(mempcpy_end); +ATF_TC_HEAD(mempcpy_end, tc) +{ +} +ATF_TC_BODY(mempcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(mempcpy_heap_before_end); +ATF_TC_HEAD(mempcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(mempcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(mempcpy_heap_end); +ATF_TC_HEAD(mempcpy_heap_end, tc) +{ +} +ATF_TC_BODY(mempcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(mempcpy_heap_after_end); +ATF_TC_HEAD(mempcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(mempcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(memmove_before_end); +ATF_TC_HEAD(memmove_before_end, tc) +{ +} +ATF_TC_BODY(memmove_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + memmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memmove_end); +ATF_TC_HEAD(memmove_end, tc) +{ +} +ATF_TC_BODY(memmove_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + memmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memmove_heap_before_end); +ATF_TC_HEAD(memmove_heap_before_end, tc) +{ +} +ATF_TC_BODY(memmove_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + memmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memmove_heap_end); +ATF_TC_HEAD(memmove_heap_end, tc) +{ +} +ATF_TC_BODY(memmove_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + memmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(memmove_heap_after_end); +ATF_TC_HEAD(memmove_heap_after_end, tc) +{ +} +ATF_TC_BODY(memmove_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + memmove(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(memset_before_end); +ATF_TC_HEAD(memset_before_end, tc) +{ +} +ATF_TC_BODY(memset_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + memset(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_end); +ATF_TC_HEAD(memset_end, tc) +{ +} +ATF_TC_BODY(memset_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + memset(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_heap_before_end); +ATF_TC_HEAD(memset_heap_before_end, tc) +{ +} +ATF_TC_BODY(memset_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + memset(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_heap_end); +ATF_TC_HEAD(memset_heap_end, tc) +{ +} +ATF_TC_BODY(memset_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + memset(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_heap_after_end); +ATF_TC_HEAD(memset_heap_after_end, tc) +{ +} +ATF_TC_BODY(memset_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + memset(__stack.__buf, 0, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(memset_explicit_before_end); +ATF_TC_HEAD(memset_explicit_before_end, tc) +{ +} +ATF_TC_BODY(memset_explicit_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + memset_explicit(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_explicit_end); +ATF_TC_HEAD(memset_explicit_end, tc) +{ +} +ATF_TC_BODY(memset_explicit_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + memset_explicit(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_explicit_heap_before_end); +ATF_TC_HEAD(memset_explicit_heap_before_end, tc) +{ +} +ATF_TC_BODY(memset_explicit_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + memset_explicit(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_explicit_heap_end); +ATF_TC_HEAD(memset_explicit_heap_end, tc) +{ +} +ATF_TC_BODY(memset_explicit_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + memset_explicit(__stack.__buf, 0, __len); +#undef BUF + +} + +ATF_TC(memset_explicit_heap_after_end); +ATF_TC_HEAD(memset_explicit_heap_after_end, tc) +{ +} +ATF_TC_BODY(memset_explicit_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + memset_explicit(__stack.__buf, 0, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(stpcpy_before_end); +ATF_TC_HEAD(stpcpy_before_end, tc) +{ +} +ATF_TC_BODY(stpcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(stpcpy_end); +ATF_TC_HEAD(stpcpy_end, tc) +{ +} +ATF_TC_BODY(stpcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(stpcpy_heap_before_end); +ATF_TC_HEAD(stpcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(stpcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(stpcpy_heap_end); +ATF_TC_HEAD(stpcpy_heap_end, tc) +{ +} +ATF_TC_BODY(stpcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(stpcpy_heap_after_end); +ATF_TC_HEAD(stpcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(stpcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpcpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(stpncpy_before_end); +ATF_TC_HEAD(stpncpy_before_end, tc) +{ +} +ATF_TC_BODY(stpncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(stpncpy_end); +ATF_TC_HEAD(stpncpy_end, tc) +{ +} +ATF_TC_BODY(stpncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(stpncpy_heap_before_end); +ATF_TC_HEAD(stpncpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(stpncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(stpncpy_heap_end); +ATF_TC_HEAD(stpncpy_heap_end, tc) +{ +} +ATF_TC_BODY(stpncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(stpncpy_heap_after_end); +ATF_TC_HEAD(stpncpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(stpncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + stpncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strcat_before_end); +ATF_TC_HEAD(strcat_before_end, tc) +{ +} +ATF_TC_BODY(strcat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcat_end); +ATF_TC_HEAD(strcat_end, tc) +{ +} +ATF_TC_BODY(strcat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcat_heap_before_end); +ATF_TC_HEAD(strcat_heap_before_end, tc) +{ +} +ATF_TC_BODY(strcat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcat_heap_end); +ATF_TC_HEAD(strcat_heap_end, tc) +{ +} +ATF_TC_BODY(strcat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcat_heap_after_end); +ATF_TC_HEAD(strcat_heap_after_end, tc) +{ +} +ATF_TC_BODY(strcat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcat(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strlcat_before_end); +ATF_TC_HEAD(strlcat_before_end, tc) +{ +} +ATF_TC_BODY(strlcat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcat_end); +ATF_TC_HEAD(strlcat_end, tc) +{ +} +ATF_TC_BODY(strlcat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcat_heap_before_end); +ATF_TC_HEAD(strlcat_heap_before_end, tc) +{ +} +ATF_TC_BODY(strlcat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcat_heap_end); +ATF_TC_HEAD(strlcat_heap_end, tc) +{ +} +ATF_TC_BODY(strlcat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcat_heap_after_end); +ATF_TC_HEAD(strlcat_heap_after_end, tc) +{ +} +ATF_TC_BODY(strlcat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strncat_before_end); +ATF_TC_HEAD(strncat_before_end, tc) +{ +} +ATF_TC_BODY(strncat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncat_end); +ATF_TC_HEAD(strncat_end, tc) +{ +} +ATF_TC_BODY(strncat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncat_heap_before_end); +ATF_TC_HEAD(strncat_heap_before_end, tc) +{ +} +ATF_TC_BODY(strncat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncat_heap_end); +ATF_TC_HEAD(strncat_heap_end, tc) +{ +} +ATF_TC_BODY(strncat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncat_heap_after_end); +ATF_TC_HEAD(strncat_heap_after_end, tc) +{ +} +ATF_TC_BODY(strncat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strcpy_before_end); +ATF_TC_HEAD(strcpy_before_end, tc) +{ +} +ATF_TC_BODY(strcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcpy_end); +ATF_TC_HEAD(strcpy_end, tc) +{ +} +ATF_TC_BODY(strcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcpy_heap_before_end); +ATF_TC_HEAD(strcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(strcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcpy_heap_end); +ATF_TC_HEAD(strcpy_heap_end, tc) +{ +} +ATF_TC_BODY(strcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(strcpy_heap_after_end); +ATF_TC_HEAD(strcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(strcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strcpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strlcpy_before_end); +ATF_TC_HEAD(strlcpy_before_end, tc) +{ +} +ATF_TC_BODY(strlcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcpy_end); +ATF_TC_HEAD(strlcpy_end, tc) +{ +} +ATF_TC_BODY(strlcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcpy_heap_before_end); +ATF_TC_HEAD(strlcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(strlcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcpy_heap_end); +ATF_TC_HEAD(strlcpy_heap_end, tc) +{ +} +ATF_TC_BODY(strlcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strlcpy_heap_after_end); +ATF_TC_HEAD(strlcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(strlcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(strncpy_before_end); +ATF_TC_HEAD(strncpy_before_end, tc) +{ +} +ATF_TC_BODY(strncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncpy_end); +ATF_TC_HEAD(strncpy_end, tc) +{ +} +ATF_TC_BODY(strncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncpy_heap_before_end); +ATF_TC_HEAD(strncpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(strncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncpy_heap_end); +ATF_TC_HEAD(strncpy_heap_end, tc) +{ +} +ATF_TC_BODY(strncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(strncpy_heap_after_end); +ATF_TC_HEAD(strncpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(strncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, memcpy_before_end); + ATF_TP_ADD_TC(tp, memcpy_end); + ATF_TP_ADD_TC(tp, memcpy_heap_before_end); + ATF_TP_ADD_TC(tp, memcpy_heap_end); + ATF_TP_ADD_TC(tp, memcpy_heap_after_end); + ATF_TP_ADD_TC(tp, mempcpy_before_end); + ATF_TP_ADD_TC(tp, mempcpy_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_before_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_after_end); + ATF_TP_ADD_TC(tp, memmove_before_end); + ATF_TP_ADD_TC(tp, memmove_end); + ATF_TP_ADD_TC(tp, memmove_heap_before_end); + ATF_TP_ADD_TC(tp, memmove_heap_end); + ATF_TP_ADD_TC(tp, memmove_heap_after_end); + ATF_TP_ADD_TC(tp, memset_before_end); + ATF_TP_ADD_TC(tp, memset_end); + ATF_TP_ADD_TC(tp, memset_heap_before_end); + ATF_TP_ADD_TC(tp, memset_heap_end); + ATF_TP_ADD_TC(tp, memset_heap_after_end); + ATF_TP_ADD_TC(tp, memset_explicit_before_end); + ATF_TP_ADD_TC(tp, memset_explicit_end); + ATF_TP_ADD_TC(tp, memset_explicit_heap_before_end); + ATF_TP_ADD_TC(tp, memset_explicit_heap_end); + ATF_TP_ADD_TC(tp, memset_explicit_heap_after_end); + ATF_TP_ADD_TC(tp, stpcpy_before_end); + ATF_TP_ADD_TC(tp, stpcpy_end); + ATF_TP_ADD_TC(tp, stpcpy_heap_before_end); + ATF_TP_ADD_TC(tp, stpcpy_heap_end); + ATF_TP_ADD_TC(tp, stpcpy_heap_after_end); + ATF_TP_ADD_TC(tp, stpncpy_before_end); + ATF_TP_ADD_TC(tp, stpncpy_end); + ATF_TP_ADD_TC(tp, stpncpy_heap_before_end); + ATF_TP_ADD_TC(tp, stpncpy_heap_end); + ATF_TP_ADD_TC(tp, stpncpy_heap_after_end); + ATF_TP_ADD_TC(tp, strcat_before_end); + ATF_TP_ADD_TC(tp, strcat_end); + ATF_TP_ADD_TC(tp, strcat_heap_before_end); + ATF_TP_ADD_TC(tp, strcat_heap_end); + ATF_TP_ADD_TC(tp, strcat_heap_after_end); + ATF_TP_ADD_TC(tp, strlcat_before_end); + ATF_TP_ADD_TC(tp, strlcat_end); + ATF_TP_ADD_TC(tp, strlcat_heap_before_end); + ATF_TP_ADD_TC(tp, strlcat_heap_end); + ATF_TP_ADD_TC(tp, strlcat_heap_after_end); + ATF_TP_ADD_TC(tp, strncat_before_end); + ATF_TP_ADD_TC(tp, strncat_end); + ATF_TP_ADD_TC(tp, strncat_heap_before_end); + ATF_TP_ADD_TC(tp, strncat_heap_end); + ATF_TP_ADD_TC(tp, strncat_heap_after_end); + ATF_TP_ADD_TC(tp, strcpy_before_end); + ATF_TP_ADD_TC(tp, strcpy_end); + ATF_TP_ADD_TC(tp, strcpy_heap_before_end); + ATF_TP_ADD_TC(tp, strcpy_heap_end); + ATF_TP_ADD_TC(tp, strcpy_heap_after_end); + ATF_TP_ADD_TC(tp, strlcpy_before_end); + ATF_TP_ADD_TC(tp, strlcpy_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_before_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_after_end); + ATF_TP_ADD_TC(tp, strncpy_before_end); + ATF_TP_ADD_TC(tp, strncpy_end); + ATF_TP_ADD_TC(tp, strncpy_heap_before_end); + ATF_TP_ADD_TC(tp, strncpy_heap_end); + ATF_TP_ADD_TC(tp, strncpy_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c new file mode 100644 index 000000000000..9f7d37a2480e --- /dev/null +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -0,0 +1,615 @@ +/* @generated by `generate-fortify-tests.lua "strings"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(bcopy_before_end); +ATF_TC_HEAD(bcopy_before_end, tc) +{ +} +ATF_TC_BODY(bcopy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + bcopy(src, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bcopy_end); +ATF_TC_HEAD(bcopy_end, tc) +{ +} +ATF_TC_BODY(bcopy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + bcopy(src, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bcopy_heap_before_end); +ATF_TC_HEAD(bcopy_heap_before_end, tc) +{ +} +ATF_TC_BODY(bcopy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + bcopy(src, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bcopy_heap_end); +ATF_TC_HEAD(bcopy_heap_end, tc) +{ +} +ATF_TC_BODY(bcopy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + bcopy(src, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bcopy_heap_after_end); +ATF_TC_HEAD(bcopy_heap_after_end, tc) +{ +} +ATF_TC_BODY(bcopy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + bcopy(src, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(bzero_before_end); +ATF_TC_HEAD(bzero_before_end, tc) +{ +} +ATF_TC_BODY(bzero_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bzero_end); +ATF_TC_HEAD(bzero_end, tc) +{ +} +ATF_TC_BODY(bzero_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bzero_heap_before_end); +ATF_TC_HEAD(bzero_heap_before_end, tc) +{ +} +ATF_TC_BODY(bzero_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bzero_heap_end); +ATF_TC_HEAD(bzero_heap_end, tc) +{ +} +ATF_TC_BODY(bzero_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(bzero_heap_after_end); +ATF_TC_HEAD(bzero_heap_after_end, tc) +{ +} +ATF_TC_BODY(bzero_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + bzero(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(explicit_bzero_before_end); +ATF_TC_HEAD(explicit_bzero_before_end, tc) +{ +} +ATF_TC_BODY(explicit_bzero_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(explicit_bzero_end); +ATF_TC_HEAD(explicit_bzero_end, tc) +{ +} +ATF_TC_BODY(explicit_bzero_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(explicit_bzero_heap_before_end); +ATF_TC_HEAD(explicit_bzero_heap_before_end, tc) +{ +} +ATF_TC_BODY(explicit_bzero_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(explicit_bzero_heap_end); +ATF_TC_HEAD(explicit_bzero_heap_end, tc) +{ +} +ATF_TC_BODY(explicit_bzero_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(explicit_bzero_heap_after_end); +ATF_TC_HEAD(explicit_bzero_heap_after_end, tc) +{ +} +ATF_TC_BODY(explicit_bzero_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, bcopy_before_end); + ATF_TP_ADD_TC(tp, bcopy_end); + ATF_TP_ADD_TC(tp, bcopy_heap_before_end); + ATF_TP_ADD_TC(tp, bcopy_heap_end); + ATF_TP_ADD_TC(tp, bcopy_heap_after_end); + ATF_TP_ADD_TC(tp, bzero_before_end); + ATF_TP_ADD_TC(tp, bzero_end); + ATF_TP_ADD_TC(tp, bzero_heap_before_end); + ATF_TP_ADD_TC(tp, bzero_heap_end); + ATF_TP_ADD_TC(tp, bzero_heap_after_end); + ATF_TP_ADD_TC(tp, explicit_bzero_before_end); + ATF_TP_ADD_TC(tp, explicit_bzero_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_before_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_uio_test.c b/lib/libc/tests/secure/fortify_uio_test.c new file mode 100644 index 000000000000..46b46ed2f7df --- /dev/null +++ b/lib/libc/tests/secure/fortify_uio_test.c @@ -0,0 +1,917 @@ +/* @generated by `generate-fortify-tests.lua "uio"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(readv_before_end); +ATF_TC_HEAD(readv_before_end, tc) +{ +} +ATF_TC_BODY(readv_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + + readv(STDIN_FILENO, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readv_end); +ATF_TC_HEAD(readv_end, tc) +{ +} +ATF_TC_BODY(readv_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + + readv(STDIN_FILENO, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readv_after_end); +ATF_TC_HEAD(readv_after_end, tc) +{ +} +ATF_TC_BODY(readv_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + readv(STDIN_FILENO, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(readv_heap_before_end); +ATF_TC_HEAD(readv_heap_before_end, tc) +{ +} +ATF_TC_BODY(readv_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + readv(STDIN_FILENO, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readv_heap_end); +ATF_TC_HEAD(readv_heap_end, tc) +{ +} +ATF_TC_BODY(readv_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + readv(STDIN_FILENO, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readv_heap_after_end); +ATF_TC_HEAD(readv_heap_after_end, tc) +{ +} +ATF_TC_BODY(readv_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + readv(STDIN_FILENO, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(readv_iov_before_end); +ATF_TC_HEAD(readv_iov_before_end, tc) +{ +} +ATF_TC_BODY(readv_iov_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + readv(STDIN_FILENO, iov, nitems(iov)); +#undef BUF + +} + +ATF_TC(readv_iov_end); +ATF_TC_HEAD(readv_iov_end, tc) +{ +} +ATF_TC_BODY(readv_iov_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + readv(STDIN_FILENO, iov, nitems(iov)); +#undef BUF + +} + +ATF_TC(readv_iov_heap_before_end); +ATF_TC_HEAD(readv_iov_heap_before_end, tc) +{ +} +ATF_TC_BODY(readv_iov_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + readv(STDIN_FILENO, iov, nitems(iov)); +#undef BUF + +} + +ATF_TC(readv_iov_heap_end); +ATF_TC_HEAD(readv_iov_heap_end, tc) +{ +} +ATF_TC_BODY(readv_iov_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + readv(STDIN_FILENO, iov, nitems(iov)); +#undef BUF + +} + +ATF_TC(readv_iov_heap_after_end); +ATF_TC_HEAD(readv_iov_heap_after_end, tc) +{ +} +ATF_TC_BODY(readv_iov_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + struct iovec iov[1]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + readv(STDIN_FILENO, iov, nitems(iov)); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(preadv_before_end); +ATF_TC_HEAD(preadv_before_end, tc) +{ +} +ATF_TC_BODY(preadv_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + + preadv(STDIN_FILENO, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(preadv_end); +ATF_TC_HEAD(preadv_end, tc) +{ +} +ATF_TC_BODY(preadv_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + + preadv(STDIN_FILENO, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(preadv_after_end); +ATF_TC_HEAD(preadv_after_end, tc) +{ +} +ATF_TC_BODY(preadv_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + struct iovec __buf[2]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + preadv(STDIN_FILENO, __stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(preadv_heap_before_end); +ATF_TC_HEAD(preadv_heap_before_end, tc) +{ +} +ATF_TC_BODY(preadv_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + preadv(STDIN_FILENO, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(preadv_heap_end); +ATF_TC_HEAD(preadv_heap_end, tc) +{ +} +ATF_TC_BODY(preadv_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + preadv(STDIN_FILENO, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(preadv_heap_after_end); +ATF_TC_HEAD(preadv_heap_after_end, tc) +{ +} +ATF_TC_BODY(preadv_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + struct iovec * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2); + const size_t __len = 2 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + preadv(STDIN_FILENO, __stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(preadv_iov_before_end); +ATF_TC_HEAD(preadv_iov_before_end, tc) +{ +} +ATF_TC_BODY(preadv_iov_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + preadv(STDIN_FILENO, iov, nitems(iov), 0); +#undef BUF + +} + +ATF_TC(preadv_iov_end); +ATF_TC_HEAD(preadv_iov_end, tc) +{ +} +ATF_TC_BODY(preadv_iov_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + preadv(STDIN_FILENO, iov, nitems(iov), 0); +#undef BUF + +} + +ATF_TC(preadv_iov_heap_before_end); +ATF_TC_HEAD(preadv_iov_heap_before_end, tc) +{ +} +ATF_TC_BODY(preadv_iov_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + preadv(STDIN_FILENO, iov, nitems(iov), 0); +#undef BUF + +} + +ATF_TC(preadv_iov_heap_end); +ATF_TC_HEAD(preadv_iov_heap_end, tc) +{ +} +ATF_TC_BODY(preadv_iov_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + struct iovec iov[1]; + + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + preadv(STDIN_FILENO, iov, nitems(iov), 0); +#undef BUF + +} + +ATF_TC(preadv_iov_heap_after_end); +ATF_TC_HEAD(preadv_iov_heap_after_end, tc) +{ +} +ATF_TC_BODY(preadv_iov_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + struct iovec iov[1]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); + + preadv(STDIN_FILENO, iov, nitems(iov), 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, readv_before_end); + ATF_TP_ADD_TC(tp, readv_end); + ATF_TP_ADD_TC(tp, readv_after_end); + ATF_TP_ADD_TC(tp, readv_heap_before_end); + ATF_TP_ADD_TC(tp, readv_heap_end); + ATF_TP_ADD_TC(tp, readv_heap_after_end); + ATF_TP_ADD_TC(tp, readv_iov_before_end); + ATF_TP_ADD_TC(tp, readv_iov_end); + ATF_TP_ADD_TC(tp, readv_iov_heap_before_end); + ATF_TP_ADD_TC(tp, readv_iov_heap_end); + ATF_TP_ADD_TC(tp, readv_iov_heap_after_end); + ATF_TP_ADD_TC(tp, preadv_before_end); + ATF_TP_ADD_TC(tp, preadv_end); + ATF_TP_ADD_TC(tp, preadv_after_end); + ATF_TP_ADD_TC(tp, preadv_heap_before_end); + ATF_TP_ADD_TC(tp, preadv_heap_end); + ATF_TP_ADD_TC(tp, preadv_heap_after_end); + ATF_TP_ADD_TC(tp, preadv_iov_before_end); + ATF_TP_ADD_TC(tp, preadv_iov_end); + ATF_TP_ADD_TC(tp, preadv_iov_heap_before_end); + ATF_TP_ADD_TC(tp, preadv_iov_heap_end); + ATF_TP_ADD_TC(tp, preadv_iov_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c new file mode 100644 index 000000000000..b12ef2bbb8ea --- /dev/null +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -0,0 +1,2199 @@ +/* @generated by `generate-fortify-tests.lua "unistd"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +#define JAIL_HOSTNAME "host.example.com" +#define JAIL_DOMAINNAME "example.com" +static void +dhost_jail(void) +{ + struct iovec iov[4]; + int jid; + + iov[0].iov_base = __DECONST(char *, "host.hostname"); + iov[0].iov_len = sizeof("host.hostname"); + iov[1].iov_base = __DECONST(char *, JAIL_HOSTNAME); + iov[1].iov_len = sizeof(JAIL_HOSTNAME); + iov[2].iov_base = __DECONST(char *, "host.domainname"); + iov[2].iov_len = sizeof("host.domainname"); + iov[3].iov_base = __DECONST(char *, JAIL_DOMAINNAME); + iov[3].iov_len = sizeof(JAIL_DOMAINNAME); + + jid = jail_set(iov, nitems(iov), JAIL_CREATE | JAIL_ATTACH); + ATF_REQUIRE_MSG(jid > 0, "Jail creation failed: %s", strerror(errno)); +} + +ATF_TC(getcwd_before_end); +ATF_TC_HEAD(getcwd_before_end, tc) +{ +} +ATF_TC_BODY(getcwd_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[8]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 8 - 1; + const size_t __idx __unused = __len - 1; + + getcwd(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getcwd_end); +ATF_TC_HEAD(getcwd_end, tc) +{ +} +ATF_TC_BODY(getcwd_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[8]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 8; + const size_t __idx __unused = __len - 1; + + getcwd(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getcwd_heap_before_end); +ATF_TC_HEAD(getcwd_heap_before_end, tc) +{ +} +ATF_TC_BODY(getcwd_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); + const size_t __len = 8 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getcwd(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getcwd_heap_end); +ATF_TC_HEAD(getcwd_heap_end, tc) +{ +} +ATF_TC_BODY(getcwd_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); + const size_t __len = 8; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getcwd(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getcwd_heap_after_end); +ATF_TC_HEAD(getcwd_heap_after_end, tc) +{ +} +ATF_TC_BODY(getcwd_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); + const size_t __len = 8 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getcwd(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getgrouplist_before_end); +ATF_TC_HEAD(getgrouplist_before_end, tc) +{ +} +ATF_TC_BODY(getgrouplist_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC(getgrouplist_end); +ATF_TC_HEAD(getgrouplist_end, tc) +{ +} +ATF_TC_BODY(getgrouplist_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC(getgrouplist_heap_before_end); +ATF_TC_HEAD(getgrouplist_heap_before_end, tc) +{ +} +ATF_TC_BODY(getgrouplist_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC(getgrouplist_heap_end); +ATF_TC_HEAD(getgrouplist_heap_end, tc) +{ +} +ATF_TC_BODY(getgrouplist_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC(getgrouplist_heap_after_end); +ATF_TC_HEAD(getgrouplist_heap_after_end, tc) +{ +} +ATF_TC_BODY(getgrouplist_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int intlen = (int)__len; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getgroups_before_end); +ATF_TC_HEAD(getgroups_before_end, tc) +{ +} +ATF_TC_BODY(getgroups_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + + getgroups(__len, __stack.__buf); +#undef BUF + +} + +ATF_TC(getgroups_end); +ATF_TC_HEAD(getgroups_end, tc) +{ +} +ATF_TC_BODY(getgroups_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + + getgroups(__len, __stack.__buf); +#undef BUF + +} + +ATF_TC(getgroups_heap_before_end); +ATF_TC_HEAD(getgroups_heap_before_end, tc) +{ +} +ATF_TC_BODY(getgroups_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getgroups(__len, __stack.__buf); +#undef BUF + +} + +ATF_TC(getgroups_heap_end); +ATF_TC_HEAD(getgroups_heap_end, tc) +{ +} +ATF_TC_BODY(getgroups_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getgroups(__len, __stack.__buf); +#undef BUF + +} + +ATF_TC(getgroups_heap_after_end); +ATF_TC_HEAD(getgroups_heap_after_end, tc) +{ +} +ATF_TC_BODY(getgroups_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getgroups(__len, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getloginclass_before_end); +ATF_TC_HEAD(getloginclass_before_end, tc) +{ +} +ATF_TC_BODY(getloginclass_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getloginclass(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getloginclass_end); +ATF_TC_HEAD(getloginclass_end, tc) +{ +} +ATF_TC_BODY(getloginclass_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getloginclass(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getloginclass_heap_before_end); +ATF_TC_HEAD(getloginclass_heap_before_end, tc) +{ +} +ATF_TC_BODY(getloginclass_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getloginclass(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getloginclass_heap_end); +ATF_TC_HEAD(getloginclass_heap_end, tc) +{ +} +ATF_TC_BODY(getloginclass_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getloginclass(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getloginclass_heap_after_end); +ATF_TC_HEAD(getloginclass_heap_after_end, tc) +{ +} +ATF_TC_BODY(getloginclass_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getloginclass(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(pread_before_end); +ATF_TC_HEAD(pread_before_end, tc) +{ +} +ATF_TC_BODY(pread_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(pread_end); +ATF_TC_HEAD(pread_end, tc) +{ +} +ATF_TC_BODY(pread_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(pread_heap_before_end); +ATF_TC_HEAD(pread_heap_before_end, tc) +{ +} +ATF_TC_BODY(pread_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(pread_heap_end); +ATF_TC_HEAD(pread_heap_end, tc) +{ +} +ATF_TC_BODY(pread_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC(pread_heap_after_end); +ATF_TC_HEAD(pread_heap_after_end, tc) +{ +} +ATF_TC_BODY(pread_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(read_before_end); +ATF_TC_HEAD(read_before_end, tc) +{ +} +ATF_TC_BODY(read_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(read_end); +ATF_TC_HEAD(read_end, tc) +{ +} +ATF_TC_BODY(read_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(read_heap_before_end); +ATF_TC_HEAD(read_heap_before_end, tc) +{ +} +ATF_TC_BODY(read_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(read_heap_end); +ATF_TC_HEAD(read_heap_end, tc) +{ +} +ATF_TC_BODY(read_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(read_heap_after_end); +ATF_TC_HEAD(read_heap_after_end, tc) +{ +} +ATF_TC_BODY(read_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(readlink_before_end); +ATF_TC_HEAD(readlink_before_end, tc) +{ +} +ATF_TC_BODY(readlink_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlink_end); +ATF_TC_HEAD(readlink_end, tc) +{ +} +ATF_TC_BODY(readlink_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlink_heap_before_end); +ATF_TC_HEAD(readlink_heap_before_end, tc) +{ +} +ATF_TC_BODY(readlink_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlink_heap_end); +ATF_TC_HEAD(readlink_heap_end, tc) +{ +} +ATF_TC_BODY(readlink_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlink_heap_after_end); +ATF_TC_HEAD(readlink_heap_after_end, tc) +{ +} +ATF_TC_BODY(readlink_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + const char *path; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(readlinkat_before_end); +ATF_TC_HEAD(readlinkat_before_end, tc) +{ +} +ATF_TC_BODY(readlinkat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlinkat_end); +ATF_TC_HEAD(readlinkat_end, tc) +{ +} +ATF_TC_BODY(readlinkat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlinkat_heap_before_end); +ATF_TC_HEAD(readlinkat_heap_before_end, tc) +{ +} +ATF_TC_BODY(readlinkat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlinkat_heap_end); +ATF_TC_HEAD(readlinkat_heap_end, tc) +{ +} +ATF_TC_BODY(readlinkat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(readlinkat_heap_after_end); +ATF_TC_HEAD(readlinkat_heap_after_end, tc) +{ +} +ATF_TC_BODY(readlinkat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + const char *path; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getdomainname_before_end); +ATF_TC_HEAD(getdomainname_before_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(getdomainname_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[12]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 12 - 1; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getdomainname_end); +ATF_TC_HEAD(getdomainname_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(getdomainname_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[12]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 12; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getdomainname_heap_before_end); +ATF_TC_HEAD(getdomainname_heap_before_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(getdomainname_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (12); + const size_t __len = 12 - 1; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getdomainname_heap_end); +ATF_TC_HEAD(getdomainname_heap_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(getdomainname_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (12); + const size_t __len = 12; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getdomainname_heap_after_end); +ATF_TC_HEAD(getdomainname_heap_after_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(getdomainname_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (12); + const size_t __len = 12 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + dhost_jail(); + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getentropy_before_end); +ATF_TC_HEAD(getentropy_before_end, tc) +{ +} +ATF_TC_BODY(getentropy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getentropy_end); +ATF_TC_HEAD(getentropy_end, tc) +{ +} +ATF_TC_BODY(getentropy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getentropy_heap_before_end); +ATF_TC_HEAD(getentropy_heap_before_end, tc) +{ +} +ATF_TC_BODY(getentropy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getentropy_heap_end); +ATF_TC_HEAD(getentropy_heap_end, tc) +{ +} +ATF_TC_BODY(getentropy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getentropy_heap_after_end); +ATF_TC_HEAD(getentropy_heap_after_end, tc) +{ +} +ATF_TC_BODY(getentropy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(gethostname_before_end); +ATF_TC_HEAD(gethostname_before_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(gethostname_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[17]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 17 - 1; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gethostname_end); +ATF_TC_HEAD(gethostname_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(gethostname_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[17]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 17; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gethostname_heap_before_end); +ATF_TC_HEAD(gethostname_heap_before_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(gethostname_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (17); + const size_t __len = 17 - 1; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gethostname_heap_end); +ATF_TC_HEAD(gethostname_heap_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(gethostname_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (17); + const size_t __len = 17; + const size_t __idx __unused = __len - 1; + + dhost_jail(); + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(gethostname_heap_after_end); +ATF_TC_HEAD(gethostname_heap_after_end, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(gethostname_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (17); + const size_t __len = 17 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + dhost_jail(); + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(getlogin_r_before_end); +ATF_TC_HEAD(getlogin_r_before_end, tc) +{ +} +ATF_TC_BODY(getlogin_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[MAXLOGNAME + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = MAXLOGNAME + 1 - 1; + const size_t __idx __unused = __len - 1; + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getlogin_r_end); +ATF_TC_HEAD(getlogin_r_end, tc) +{ +} +ATF_TC_BODY(getlogin_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[MAXLOGNAME + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = MAXLOGNAME + 1; + const size_t __idx __unused = __len - 1; + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getlogin_r_heap_before_end); +ATF_TC_HEAD(getlogin_r_heap_before_end, tc) +{ +} +ATF_TC_BODY(getlogin_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getlogin_r_heap_end); +ATF_TC_HEAD(getlogin_r_heap_end, tc) +{ +} +ATF_TC_BODY(getlogin_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getlogin_r_heap_after_end); +ATF_TC_HEAD(getlogin_r_heap_after_end, tc) +{ +} +ATF_TC_BODY(getlogin_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(ttyname_r_before_end); +ATF_TC_HEAD(ttyname_r_before_end, tc) +{ +} +ATF_TC_BODY(ttyname_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(ttyname_r_end); +ATF_TC_HEAD(ttyname_r_end, tc) +{ +} +ATF_TC_BODY(ttyname_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(ttyname_r_heap_before_end); +ATF_TC_HEAD(ttyname_r_heap_before_end, tc) +{ +} +ATF_TC_BODY(ttyname_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(ttyname_r_heap_end); +ATF_TC_HEAD(ttyname_r_heap_end, tc) +{ +} +ATF_TC_BODY(ttyname_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(ttyname_r_heap_after_end); +ATF_TC_HEAD(ttyname_r_heap_after_end, tc) +{ +} +ATF_TC_BODY(ttyname_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getcwd_before_end); + ATF_TP_ADD_TC(tp, getcwd_end); + ATF_TP_ADD_TC(tp, getcwd_heap_before_end); + ATF_TP_ADD_TC(tp, getcwd_heap_end); + ATF_TP_ADD_TC(tp, getcwd_heap_after_end); + ATF_TP_ADD_TC(tp, getgrouplist_before_end); + ATF_TP_ADD_TC(tp, getgrouplist_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_before_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_after_end); + ATF_TP_ADD_TC(tp, getgroups_before_end); + ATF_TP_ADD_TC(tp, getgroups_end); + ATF_TP_ADD_TC(tp, getgroups_heap_before_end); + ATF_TP_ADD_TC(tp, getgroups_heap_end); + ATF_TP_ADD_TC(tp, getgroups_heap_after_end); + ATF_TP_ADD_TC(tp, getloginclass_before_end); + ATF_TP_ADD_TC(tp, getloginclass_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_before_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_after_end); + ATF_TP_ADD_TC(tp, pread_before_end); + ATF_TP_ADD_TC(tp, pread_end); + ATF_TP_ADD_TC(tp, pread_heap_before_end); + ATF_TP_ADD_TC(tp, pread_heap_end); + ATF_TP_ADD_TC(tp, pread_heap_after_end); + ATF_TP_ADD_TC(tp, read_before_end); + ATF_TP_ADD_TC(tp, read_end); + ATF_TP_ADD_TC(tp, read_heap_before_end); + ATF_TP_ADD_TC(tp, read_heap_end); + ATF_TP_ADD_TC(tp, read_heap_after_end); + ATF_TP_ADD_TC(tp, readlink_before_end); + ATF_TP_ADD_TC(tp, readlink_end); + ATF_TP_ADD_TC(tp, readlink_heap_before_end); + ATF_TP_ADD_TC(tp, readlink_heap_end); + ATF_TP_ADD_TC(tp, readlink_heap_after_end); + ATF_TP_ADD_TC(tp, readlinkat_before_end); + ATF_TP_ADD_TC(tp, readlinkat_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_before_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_after_end); + ATF_TP_ADD_TC(tp, getdomainname_before_end); + ATF_TP_ADD_TC(tp, getdomainname_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_before_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_after_end); + ATF_TP_ADD_TC(tp, getentropy_before_end); + ATF_TP_ADD_TC(tp, getentropy_end); + ATF_TP_ADD_TC(tp, getentropy_heap_before_end); + ATF_TP_ADD_TC(tp, getentropy_heap_end); + ATF_TP_ADD_TC(tp, getentropy_heap_after_end); + ATF_TP_ADD_TC(tp, gethostname_before_end); + ATF_TP_ADD_TC(tp, gethostname_end); + ATF_TP_ADD_TC(tp, gethostname_heap_before_end); + ATF_TP_ADD_TC(tp, gethostname_heap_end); + ATF_TP_ADD_TC(tp, gethostname_heap_after_end); + ATF_TP_ADD_TC(tp, getlogin_r_before_end); + ATF_TP_ADD_TC(tp, getlogin_r_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_before_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_after_end); + ATF_TP_ADD_TC(tp, ttyname_r_before_end); + ATF_TP_ADD_TC(tp, ttyname_r_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_before_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_wchar_test.c b/lib/libc/tests/secure/fortify_wchar_test.c new file mode 100644 index 000000000000..43c7997bc6a3 --- /dev/null +++ b/lib/libc/tests/secure/fortify_wchar_test.c @@ -0,0 +1,2124 @@ +/* @generated by `generate-fortify-tests.lua "wchar"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(wmemcpy_before_end); +ATF_TC_HEAD(wmemcpy_before_end, tc) +{ +} +ATF_TC_BODY(wmemcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemcpy_end); +ATF_TC_HEAD(wmemcpy_end, tc) +{ +} +ATF_TC_BODY(wmemcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemcpy_heap_before_end); +ATF_TC_HEAD(wmemcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wmemcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemcpy_heap_end); +ATF_TC_HEAD(wmemcpy_heap_end, tc) +{ +} +ATF_TC_BODY(wmemcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemcpy_heap_after_end); +ATF_TC_HEAD(wmemcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wmemcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wmempcpy_before_end); +ATF_TC_HEAD(wmempcpy_before_end, tc) +{ +} +ATF_TC_BODY(wmempcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmempcpy_end); +ATF_TC_HEAD(wmempcpy_end, tc) +{ +} +ATF_TC_BODY(wmempcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmempcpy_heap_before_end); +ATF_TC_HEAD(wmempcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wmempcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmempcpy_heap_end); +ATF_TC_HEAD(wmempcpy_heap_end, tc) +{ +} +ATF_TC_BODY(wmempcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmempcpy_heap_after_end); +ATF_TC_HEAD(wmempcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wmempcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmempcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wmemmove_before_end); +ATF_TC_HEAD(wmemmove_before_end, tc) +{ +} +ATF_TC_BODY(wmemmove_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemmove_end); +ATF_TC_HEAD(wmemmove_end, tc) +{ +} +ATF_TC_BODY(wmemmove_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemmove_heap_before_end); +ATF_TC_HEAD(wmemmove_heap_before_end, tc) +{ +} +ATF_TC_BODY(wmemmove_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemmove_heap_end); +ATF_TC_HEAD(wmemmove_heap_end, tc) +{ +} +ATF_TC_BODY(wmemmove_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wmemmove_heap_after_end); +ATF_TC_HEAD(wmemmove_heap_after_end, tc) +{ +} +ATF_TC_BODY(wmemmove_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemmove(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wmemset_before_end); +ATF_TC_HEAD(wmemset_before_end, tc) +{ +} +ATF_TC_BODY(wmemset_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC(wmemset_end); +ATF_TC_HEAD(wmemset_end, tc) +{ +} +ATF_TC_BODY(wmemset_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC(wmemset_heap_before_end); +ATF_TC_HEAD(wmemset_heap_before_end, tc) +{ +} +ATF_TC_BODY(wmemset_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC(wmemset_heap_end); +ATF_TC_HEAD(wmemset_heap_end, tc) +{ +} +ATF_TC_BODY(wmemset_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); +#undef BUF + +} + +ATF_TC(wmemset_heap_after_end); +ATF_TC_HEAD(wmemset_heap_after_end, tc) +{ +} +ATF_TC_BODY(wmemset_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + wmemset(__stack.__buf, L'0', __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcpcpy_before_end); +ATF_TC_HEAD(wcpcpy_before_end, tc) +{ +} +ATF_TC_BODY(wcpcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcpcpy_end); +ATF_TC_HEAD(wcpcpy_end, tc) +{ +} +ATF_TC_BODY(wcpcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcpcpy_heap_before_end); +ATF_TC_HEAD(wcpcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcpcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcpcpy_heap_end); +ATF_TC_HEAD(wcpcpy_heap_end, tc) +{ +} +ATF_TC_BODY(wcpcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcpcpy_heap_after_end); +ATF_TC_HEAD(wcpcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcpcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpcpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcpncpy_before_end); +ATF_TC_HEAD(wcpncpy_before_end, tc) +{ +} +ATF_TC_BODY(wcpncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcpncpy_end); +ATF_TC_HEAD(wcpncpy_end, tc) +{ +} +ATF_TC_BODY(wcpncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcpncpy_heap_before_end); +ATF_TC_HEAD(wcpncpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcpncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcpncpy_heap_end); +ATF_TC_HEAD(wcpncpy_heap_end, tc) +{ +} +ATF_TC_BODY(wcpncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcpncpy_heap_after_end); +ATF_TC_HEAD(wcpncpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcpncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcpncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcscat_before_end); +ATF_TC_HEAD(wcscat_before_end, tc) +{ +} +ATF_TC_BODY(wcscat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscat_end); +ATF_TC_HEAD(wcscat_end, tc) +{ +} +ATF_TC_BODY(wcscat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscat_heap_before_end); +ATF_TC_HEAD(wcscat_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcscat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscat_heap_end); +ATF_TC_HEAD(wcscat_heap_end, tc) +{ +} +ATF_TC_BODY(wcscat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscat_heap_after_end); +ATF_TC_HEAD(wcscat_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcscat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscat(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcslcat_before_end); +ATF_TC_HEAD(wcslcat_before_end, tc) +{ +} +ATF_TC_BODY(wcslcat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcat_end); +ATF_TC_HEAD(wcslcat_end, tc) +{ +} +ATF_TC_BODY(wcslcat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcat_heap_before_end); +ATF_TC_HEAD(wcslcat_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcslcat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcat_heap_end); +ATF_TC_HEAD(wcslcat_heap_end, tc) +{ +} +ATF_TC_BODY(wcslcat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcat_heap_after_end); +ATF_TC_HEAD(wcslcat_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcslcat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcsncat_before_end); +ATF_TC_HEAD(wcsncat_before_end, tc) +{ +} +ATF_TC_BODY(wcsncat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncat_end); +ATF_TC_HEAD(wcsncat_end, tc) +{ +} +ATF_TC_BODY(wcsncat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncat_heap_before_end); +ATF_TC_HEAD(wcsncat_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcsncat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncat_heap_end); +ATF_TC_HEAD(wcsncat_heap_end, tc) +{ +} +ATF_TC_BODY(wcsncat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncat_heap_after_end); +ATF_TC_HEAD(wcsncat_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcsncat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcscpy_before_end); +ATF_TC_HEAD(wcscpy_before_end, tc) +{ +} +ATF_TC_BODY(wcscpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscpy_end); +ATF_TC_HEAD(wcscpy_end, tc) +{ +} +ATF_TC_BODY(wcscpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscpy_heap_before_end); +ATF_TC_HEAD(wcscpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcscpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscpy_heap_end); +ATF_TC_HEAD(wcscpy_heap_end, tc) +{ +} +ATF_TC_BODY(wcscpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); +#undef BUF + +} + +ATF_TC(wcscpy_heap_after_end); +ATF_TC_HEAD(wcscpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcscpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcscpy(__stack.__buf, src); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcslcpy_before_end); +ATF_TC_HEAD(wcslcpy_before_end, tc) +{ +} +ATF_TC_BODY(wcslcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcpy_end); +ATF_TC_HEAD(wcslcpy_end, tc) +{ +} +ATF_TC_BODY(wcslcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcpy_heap_before_end); +ATF_TC_HEAD(wcslcpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcslcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcpy_heap_end); +ATF_TC_HEAD(wcslcpy_heap_end, tc) +{ +} +ATF_TC_BODY(wcslcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcslcpy_heap_after_end); +ATF_TC_HEAD(wcslcpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcslcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcslcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC(wcsncpy_before_end); +ATF_TC_HEAD(wcsncpy_before_end, tc) +{ +} +ATF_TC_BODY(wcsncpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncpy_end); +ATF_TC_HEAD(wcsncpy_end, tc) +{ +} +ATF_TC_BODY(wcsncpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + wchar_t __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncpy_heap_before_end); +ATF_TC_HEAD(wcsncpy_heap_before_end, tc) +{ +} +ATF_TC_BODY(wcsncpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncpy_heap_end); +ATF_TC_HEAD(wcsncpy_heap_end, tc) +{ +} +ATF_TC_BODY(wcsncpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + wchar_t src[__len]; + + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC(wcsncpy_heap_after_end); +ATF_TC_HEAD(wcsncpy_heap_after_end, tc) +{ +} +ATF_TC_BODY(wcsncpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + wchar_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + wchar_t src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + wcsncpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, wmemcpy_before_end); + ATF_TP_ADD_TC(tp, wmemcpy_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_end); + ATF_TP_ADD_TC(tp, wmemcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wmempcpy_before_end); + ATF_TP_ADD_TC(tp, wmempcpy_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_end); + ATF_TP_ADD_TC(tp, wmempcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wmemmove_before_end); + ATF_TP_ADD_TC(tp, wmemmove_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_before_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_end); + ATF_TP_ADD_TC(tp, wmemmove_heap_after_end); + ATF_TP_ADD_TC(tp, wmemset_before_end); + ATF_TP_ADD_TC(tp, wmemset_end); + ATF_TP_ADD_TC(tp, wmemset_heap_before_end); + ATF_TP_ADD_TC(tp, wmemset_heap_end); + ATF_TP_ADD_TC(tp, wmemset_heap_after_end); + ATF_TP_ADD_TC(tp, wcpcpy_before_end); + ATF_TP_ADD_TC(tp, wcpcpy_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_end); + ATF_TP_ADD_TC(tp, wcpcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcpncpy_before_end); + ATF_TP_ADD_TC(tp, wcpncpy_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_end); + ATF_TP_ADD_TC(tp, wcpncpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcscat_before_end); + ATF_TP_ADD_TC(tp, wcscat_end); + ATF_TP_ADD_TC(tp, wcscat_heap_before_end); + ATF_TP_ADD_TC(tp, wcscat_heap_end); + ATF_TP_ADD_TC(tp, wcscat_heap_after_end); + ATF_TP_ADD_TC(tp, wcslcat_before_end); + ATF_TP_ADD_TC(tp, wcslcat_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_before_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_end); + ATF_TP_ADD_TC(tp, wcslcat_heap_after_end); + ATF_TP_ADD_TC(tp, wcsncat_before_end); + ATF_TP_ADD_TC(tp, wcsncat_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_before_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_end); + ATF_TP_ADD_TC(tp, wcsncat_heap_after_end); + ATF_TP_ADD_TC(tp, wcscpy_before_end); + ATF_TP_ADD_TC(tp, wcscpy_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_end); + ATF_TP_ADD_TC(tp, wcscpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcslcpy_before_end); + ATF_TP_ADD_TC(tp, wcslcpy_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_end); + ATF_TP_ADD_TC(tp, wcslcpy_heap_after_end); + ATF_TP_ADD_TC(tp, wcsncpy_before_end); + ATF_TP_ADD_TC(tp, wcsncpy_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_before_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_end); + ATF_TP_ADD_TC(tp, wcsncpy_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua new file mode 100755 index 000000000000..c9cd9353a869 --- /dev/null +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -0,0 +1,1581 @@ +#!/usr/libexec/flua +-- +-- SPDX-License-Identifier: BSD-2-Clause +-- +-- Copyright (c) 2024, Klara, Inc. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- 1. Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- 2. Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- + +-- THEORY OF OPERATION +-- +-- generate-fortify-tests.lua is intended to test fortified functions as found +-- mostly in the various headers in /usr/include/ssp. Each fortified function +-- gets three basic tests: +-- +-- 1. Write just before the end of the buffer, +-- 2. Write right at the end of the buffer, +-- 3. Write just after the end of the buffer. +-- +-- Each test is actually generated twice: once with a buffer on the stack, and +-- again with a buffer on the heap, to confirm that __builtin_object_size(3) can +-- deduce the buffer size in both scenarios. The tests work by setting up the +-- stack with our buffer (and some padding on either side to avoid tripping any +-- other stack or memory protection), doing any initialization as described by +-- the test definition, then calling the fortified function with the buffer as +-- outlined by the test definition. +-- +-- For the 'before' and 'at' the end tests, we're ensuring that valid writes +-- that are on the verge of being invalid aren't accidentally being detected as +-- invalid. +-- +-- The 'after' test is the one that actually tests the functional benefit of +-- _FORTIFY_SOURCE by violating a boundary that should trigger an abort. As +-- such, this test differs more from the other two in that it has to fork() off +-- the fortified function call so that we can monitor for a SIGABRT and +-- pass/fail the test at function end appropriately. + +-- Some tests, like the FD_*() macros, may define these differently. For +-- instance, for fd sets we're varying the index we pass and not using arbitrary +-- buffers. Other tests that don't use the length in any way may physically +-- vary the buffer size for each test case when we'd typically vary the length +-- we're requesting a write for. + +local includes = { + "sys/param.h", + "sys/jail.h", + "sys/random.h", + "sys/resource.h", + "sys/select.h", + "sys/socket.h", + "sys/time.h", + "sys/uio.h", + "sys/wait.h", + "dirent.h", + "errno.h", + "fcntl.h", + "limits.h", + "poll.h", + "signal.h", + "stdio.h", + "stdlib.h", + "string.h", + "strings.h", + "sysexits.h", + "unistd.h", + "wchar.h", + "atf-c.h", +} + +local tests_added = {} + +-- Configuration for tests that want the host/domainname +local hostname = "host.example.com" +local domainname = "example.com" + +-- Some of these will need to be excluded because clang sees the wrong size when +-- an array is embedded inside a struct, we'll get something that looks more +-- like __builtin_object_size(ptr, 0) than it does the correct +-- __builtin_object_size(ptr, 1) (i.e., includes the padding after). This is +-- almost certainly a bug in llvm. +local function excludes_stack_overflow(disposition, is_heap) + return (not is_heap) and disposition > 0 +end + +local poll_init = [[ + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } +]] + +local printf_stackvars = "\tchar srcvar[__len + 10];\n" +local printf_init = [[ + memset(srcvar, 'A', sizeof(srcvar) - 1); + srcvar[sizeof(srcvar) - 1] = '\0'; +]] + +local readv_stackvars = "\tstruct iovec iov[1];\n" +local readv_init = [[ + iov[0].iov_base = __stack.__buf; + iov[0].iov_len = __len; + + replace_stdin(); +]] + +local socket_stackvars = "\tint sock[2] = { -1, -1 };\n" +local recvfrom_sockaddr_stackvars = socket_stackvars .. [[ + char data[16]; + socklen_t socklen; +]] +local recvmsg_stackvars = socket_stackvars .. "\tstruct msghdr msg;\n" +local socket_init = [[ + new_socket(sock); +]] +local socket_socklen_init = socket_init .. [[ + socklen = __len; +]] + +local stdio_init = [[ + replace_stdin(); +]] + +local string_stackvars = "\tchar src[__len];\n" +local string_init = [[ + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; +]] + +local wstring_stackvars = "\twchar_t src[__len];\n" +local wstring_init = [[ + wmemset(__stack.__buf, 0, __len); + wmemset(src, 'A', __len - 1); + src[__len - 1] = '\0'; +]] + +-- Each test entry describes how to test a given function. We need to know how +-- to construct the buffer, we need to know the argument set we're dealing with, +-- and we need to know what we're passing to each argument. We could be passing +-- fixed values, or we could be passing the __buf under test. +-- +-- definition: +-- func: name of the function under test to call +-- bufsize: size of buffer to generate, defaults to 42 +-- buftype: type of buffer to generate, defaults to unsigned char[] +-- arguments: __buf, __len, or the name of a variable placed on the stack +-- exclude: a function(disposition, is_heap) that returns true if this combo +-- should be excluded. +-- stackvars: extra variables to be placed on the stack, should be a string +-- optionally formatted with tabs and newlines +-- init: extra code to inject just before the function call for initialization +-- of the buffer or any of the above-added stackvars; also a string +-- uses_len: bool-ish, necessary if arguments doesn't include either __idx or +-- or __len so that the test generator doesn't try to vary the size of the +-- buffer instead of just manipulating __idx/__len to try and induce an +-- overflow. +-- +-- Most tests will just use the default bufsize/buftype, but under some +-- circumstances it's useful to use a different type (e.g., for alignment +-- requirements). +local all_tests = { + random = { + -- <sys/random.h> + { + func = "getrandom", + arguments = { + "__buf", + "__len", + "0", + }, + exclude = excludes_stack_overflow, + }, + }, + select = { + -- <sys/select.h> + { + func = "FD_SET", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + { + func = "FD_CLR", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + { + func = "FD_ISSET", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + }, + socket = { + -- <sys/socket.h> + { + func = "getpeername", + buftype = "struct sockaddr", + bufsize = "sizeof(struct sockaddr)", + arguments = { + "sock[0]", + "__buf", + "&socklen", + }, + exclude = excludes_stack_overflow, + stackvars = socket_stackvars .. "\tsocklen_t socklen;", + init = socket_socklen_init, + uses_len = true, + }, + { + func = "getsockname", + buftype = "struct sockaddr", + bufsize = "sizeof(struct sockaddr)", + arguments = { + "sock[0]", + "__buf", + "&socklen", + }, + exclude = excludes_stack_overflow, + stackvars = socket_stackvars .. "\tsocklen_t socklen;", + init = socket_socklen_init, + uses_len = true, + }, + { + func = "recv", + arguments = { + "sock[0]", + "__buf", + "__len", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = socket_stackvars, + init = socket_init, + }, + { + func = "recvfrom", + arguments = { + "sock[0]", + "__buf", + "__len", + "0", + "NULL", + "NULL", + }, + exclude = excludes_stack_overflow, + stackvars = socket_stackvars, + init = socket_init, + }, + { + func = "recvfrom", + variant = "sockaddr", + buftype = "struct sockaddr", + bufsize = "sizeof(struct sockaddr)", + arguments = { + "sock[0]", + "data", + "sizeof(data)", + "0", + "__buf", + "&socklen", + }, + exclude = excludes_stack_overflow, + stackvars = recvfrom_sockaddr_stackvars, + init = socket_socklen_init, + uses_len = true, + }, + { + func = "recvmsg", + variant = "msg_name", + buftype = "struct sockaddr", + bufsize = "sizeof(struct sockaddr)", + arguments = { + "sock[0]", + "&msg", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = recvmsg_stackvars, + init = [[ + memset(&msg, 0, sizeof(msg)); + msg.msg_name = BUF; + msg.msg_namelen = __len; +]], + uses_len = true, + }, + { + func = "recvmsg", + variant = "msg_iov", + arguments = { + "sock[0]", + "&msg", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = recvmsg_stackvars .. "\tstruct iovec iov[2];\n", + init = [[ + memset(&msg, 0, sizeof(msg)); + memset(&iov[0], 0, sizeof(iov)); + + /* + * We position the buffer second just so that we can confirm that the + * fortification bits are traversing the iovec correctly. + */ + iov[1].iov_base = BUF; + iov[1].iov_len = __len; + + msg.msg_iov = &iov[0]; + msg.msg_iovlen = nitems(iov); +]], + uses_len = true, + }, + { + func = "recvmsg", + variant = "msg_control", + bufsize = "CMSG_SPACE(sizeof(int))", + arguments = { + "sock[0]", + "&msg", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = recvmsg_stackvars, + init = [[ + memset(&msg, 0, sizeof(msg)); + + msg.msg_control = BUF; + msg.msg_controllen = __len; +]], + uses_len = true, + }, + { + func = "recvmmsg", + variant = "msgvec", + buftype = "struct mmsghdr[]", + bufsize = "2", + arguments = { + "sock[0]", + "__buf", + "__len", + "0", + "NULL", + }, + stackvars = socket_stackvars, + }, + { + -- We'll assume that recvmsg is covering msghdr + -- validation thoroughly enough, we'll just try tossing + -- an error in the second element of a msgvec to try and + -- make sure that each one is being validated. + func = "recvmmsg", + variant = "msghdr", + arguments = { + "sock[0]", + "&msgvec[0]", + "nitems(msgvec)", + "0", + "NULL", + }, + exclude = excludes_stack_overflow, + stackvars = socket_stackvars .. "\tstruct mmsghdr msgvec[2];\n", + init = [[ + memset(&msgvec[0], 0, sizeof(msgvec)); + + /* + * Same as above, make sure fortification isn't ignoring n > 1 elements + * of the msgvec. + */ + msgvec[1].msg_hdr.msg_control = BUF; + msgvec[1].msg_hdr.msg_controllen = __len; +]], + uses_len = true, + }, + }, + uio = { + -- <sys/uio.h> + { + func = "readv", + buftype = "struct iovec[]", + bufsize = 2, + arguments = { + "STDIN_FILENO", + "__buf", + "__len", + }, + }, + { + func = "readv", + variant = "iov", + arguments = { + "STDIN_FILENO", + "iov", + "nitems(iov)", + }, + exclude = excludes_stack_overflow, + stackvars = readv_stackvars, + init = readv_init, + uses_len = true, + }, + { + func = "preadv", + buftype = "struct iovec[]", + bufsize = 2, + arguments = { + "STDIN_FILENO", + "__buf", + "__len", + "0", + }, + }, + { + func = "preadv", + variant = "iov", + arguments = { + "STDIN_FILENO", + "iov", + "nitems(iov)", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = readv_stackvars, + init = readv_init, + uses_len = true, + }, + }, + poll = { + -- <poll.h> + { + func = "poll", + bufsize = "4", + buftype = "struct pollfd[]", + arguments = { + "__buf", + "__len", + "0", + }, + init = poll_init, + }, + { + func = "ppoll", + bufsize = "4", + buftype = "struct pollfd[]", + arguments = { + "__buf", + "__len", + "&tv", + "NULL", + }, + stackvars = "\tstruct timespec tv = { 0 };\n", + init = poll_init, + }, + }, + signal = { + -- <signal.h> + { + func = "sig2str", + bufsize = "SIG2STR_MAX", + arguments = { + "1", + "__buf", + }, + exclude = excludes_stack_overflow, + }, + }, + stdio = { + -- <stdio.h> + { + func = "ctermid", + bufsize = "L_ctermid", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "ctermid_r", + bufsize = "L_ctermid", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "fread", + arguments = { + "__buf", + "__len", + "1", + "stdin", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, + { + func = "fread_unlocked", + arguments = { + "__buf", + "__len", + "1", + "stdin", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, + { + func = "gets_s", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, + { + func = "sprintf", + arguments = { + "__buf", + "\"%.*s\"", + "(int)__len - 1", -- - 1 for NUL terminator + "srcvar", + }, + exclude = excludes_stack_overflow, + stackvars = printf_stackvars, + init = printf_init, + }, + { + func = "snprintf", + arguments = { + "__buf", + "__len", + "\"%.*s\"", + "(int)__len - 1", -- - 1 for NUL terminator + "srcvar", + }, + exclude = excludes_stack_overflow, + stackvars = printf_stackvars, + init = printf_init, + }, + { + func = "tmpnam", + bufsize = "L_tmpnam", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "fgets", + arguments = { + "__buf", + "__len", + "fp", + }, + exclude = excludes_stack_overflow, + stackvars = "\tFILE *fp;\n", + init = [[ + fp = new_fp(__len); +]], + }, + }, + stdlib = { + -- <stdlib.h> + { + func = "arc4random_buf", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "getenv_r", + arguments = { + "\"PATH\"", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "realpath", + bufsize = "PATH_MAX", + arguments = { + "\".\"", + "__buf", + }, + exclude = excludes_stack_overflow, + }, + }, + string = { + -- <string.h> + { + func = "memcpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar src[__len + 10];\n", + }, + { + func = "mempcpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar src[__len + 10];\n", + }, + { + func = "memmove", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar src[__len + 10];\n", + }, + { + func = "memset", + arguments = { + "__buf", + "0", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "memset_explicit", + arguments = { + "__buf", + "0", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "stpcpy", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + uses_len = true, + }, + { + func = "stpncpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, + { + func = "strcat", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + uses_len = true, + }, + { + func = "strlcat", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, + { + func = "strncat", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, + { + func = "strcpy", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + uses_len = true, + }, + { + func = "strlcpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, + { + func = "strncpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, + }, + strings = { + -- <strings.h> + { + func = "bcopy", + arguments = { + "src", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar src[__len + 10];\n", + }, + { + func = "bzero", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "explicit_bzero", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + }, + unistd = { + -- <unistd.h> + { + func = "getcwd", + bufsize = "8", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "getgrouplist", + bufsize = "4", + buftype = "gid_t[]", + arguments = { + "\"root\"", + "0", + "__buf", + "&intlen", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint intlen = (int)__len;\n", + uses_len = true, + }, + { + func = "getgroups", + bufsize = "4", + buftype = "gid_t[]", + arguments = { + "__len", + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "getloginclass", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "pread", + bufsize = "41", + arguments = { + "fd", + "__buf", + "__len", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint fd;\n", + init = [[ + fd = new_tmpfile(); /* Cannot fail */ +]], + }, + { + func = "read", + bufsize = "41", + arguments = { + "fd", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint fd;\n", + init = [[ + fd = new_tmpfile(); /* Cannot fail */ +]], + }, + { + func = "readlink", + arguments = { + "path", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tconst char *path;\n", + init = [[ + path = new_symlink(__len); /* Cannot fail */ +]], + }, + { + func = "readlinkat", + arguments = { + "AT_FDCWD", + "path", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tconst char *path;\n", + init = [[ + path = new_symlink(__len); /* Cannot fail */ +]], + }, + { + func = "getdomainname", + bufsize = #domainname + 1, + arguments = { + "__buf", + "__len", + }, + need_root = true, + exclude = excludes_stack_overflow, + early_init = " dhost_jail();", + }, + { + func = "getentropy", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "gethostname", + bufsize = #hostname + 1, + arguments = { + "__buf", + "__len", + }, + need_root = true, + exclude = excludes_stack_overflow, + early_init = " dhost_jail();", + }, + { + func = "getlogin_r", + bufsize = "MAXLOGNAME + 1", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "ttyname_r", + arguments = { + "fd", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint fd;\n", + early_init = [[ + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); +]] + }, + }, + wchar = { + -- <wchar.h> + { + func = "wmemcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmempcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmemmove", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\twchar_t src[__len + 10];\n", + }, + { + func = "wmemset", + buftype = "wchar_t[]", + arguments = { + "__buf", + "L'0'", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "wcpcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcpncpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcscat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcslcat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcsncat", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcscpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + uses_len = true, + }, + { + func = "wcslcpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + { + func = "wcsncpy", + buftype = "wchar_t[]", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = wstring_stackvars, + init = wstring_init, + }, + }, +} + +local function write_test_boilerplate(fh, name, body, def) + fh:write("ATF_TC(" .. name .. ");\n") + fh:write("ATF_TC_HEAD(" .. name .. ", tc)\n") + fh:write("{\n") + if def.need_root then + fh:write(" atf_tc_set_md_var(tc, \"require.user\", \"root\");\n") + end + fh:write("}\n") + + fh:write("ATF_TC_BODY(" .. name .. ", tc)\n") + fh:write("{\n" .. body .. "\n}\n\n") + return name +end + +local function generate_test_name(func, variant, disposition, heap) + local basename = func + if variant then + basename = basename .. "_" .. variant + end + if heap then + basename = basename .. "_heap" + end + if disposition < 0 then + return basename .. "_before_end" + elseif disposition == 0 then + return basename .. "_end" + else + return basename .. "_after_end" + end +end + +local function array_type(buftype) + if not buftype:match("%[%]") then + return nil + end + + return buftype:gsub("%[%]", "") +end + +local function configurable(def, idx) + local cfgitem = def[idx] + + if not cfgitem then + return nil + end + + if type(cfgitem) == "function" then + return cfgitem() + end + + return cfgitem +end + +local function generate_stackframe(buftype, bufsize, disposition, heap, def) + local function len_offset(inverted) + -- Tests that don't use __len in their arguments may use an + -- inverted sense because we can't just specify a length that + -- would induce an access just after the end. Instead, we have + -- to manipulate the buffer size to be too short so that the + -- function under test would write one too many. + if disposition < 0 then + return ((inverted and " + ") or " - ") .. "1" + elseif disposition == 0 then + return "" + else + return ((inverted and " - ") or " + ") .. "1" + end + end + + local function test_uses_len() + if def.uses_len then + return true + end + + for _, arg in ipairs(def.arguments) do + if arg:match("__len") or arg:match("__idx") then + return true + end + end + + return false + end + + + -- This is perhaps a little convoluted, but we toss the buffer into a + -- struct on the stack to guarantee that we have at least one valid + -- byte on either side of the buffer -- a measure to make sure that + -- we're tripping _FORTIFY_SOURCE specifically in the buffer + 1 case, + -- rather than some other stack or memory protection. + local vars = "\tstruct {\n" + vars = vars .. "\t\tuint8_t padding_l;\n" + + local uses_len = test_uses_len() + local bufsize_offset = len_offset(not uses_len) + local buftype_elem = array_type(buftype) + local size_expr = bufsize + + if not uses_len then + -- If the length isn't in use, we have to vary the buffer size + -- since the fortified function likely has some internal size + -- constraint that it's supposed to be checking. + size_expr = size_expr .. bufsize_offset + end + + if not heap and buftype_elem then + -- Array type: size goes after identifier + vars = vars .. "\t\t" .. buftype_elem .. + " __buf[" .. size_expr .. "];\n" + else + local basic_type = buftype_elem or buftype + + -- Heap tests obviously just put a pointer on the stack that + -- points to our new allocation, but we leave it in the padded + -- struct just to simplify our generator. + if heap then + basic_type = basic_type .. " *" + end + vars = vars .. "\t\t" .. basic_type .. " __buf;\n" + end + + -- padding_r is our just-past-the-end padding that we use to make sure + -- that there's a valid portion after the buffer that isn't being + -- included in our function calls. If we didn't have it, then we'd have + -- a hard time feeling confident that an abort on the just-after tests + -- isn't maybe from some other memory or stack protection. + vars = vars .. "\t\tuint8_t padding_r;\n" + vars = vars .. "\t} __stack;\n" + + -- Not all tests will use __bufsz, but some do for, e.g., clearing + -- memory.. + vars = vars .. "\tconst size_t __bufsz __unused = " + if heap then + local scalar = 1 + if buftype_elem then + scalar = size_expr + end + + vars = vars .. "sizeof(*__stack.__buf) * (" .. scalar .. ");\n" + else + vars = vars .. "sizeof(__stack.__buf);\n" + end + + vars = vars .. "\tconst size_t __len = " .. bufsize .. + bufsize_offset .. ";\n" + vars = vars .. "\tconst size_t __idx __unused = __len - 1;\n" + + -- For overflow testing, we need to fork() because we're expecting the + -- test to ultimately abort()/_exit(). Then we can collect the exit + -- status and report appropriately. + if disposition > 0 then + vars = vars .. "\tpid_t __child;\n" + vars = vars .. "\tint __status;\n" + end + + -- Any other stackvars defined by the test get placed after everything + -- else. + vars = vars .. (configurable(def, "stackvars") or "") + + return vars +end + +local function write_test(fh, func, disposition, heap, def) + local testname = generate_test_name(func, def.variant, disposition, heap) + local buftype = def.buftype or "unsigned char[]" + local bufsize = def.bufsize or 42 + local body = "" + + if def.exclude and def.exclude(disposition, heap) then + return + end + + local function need_addr() + return not (buftype:match("%[%]") or buftype:match("%*")) + end + + if heap then + body = body .. "#define BUF __stack.__buf\n" + else + body = body .. "#define BUF &__stack.__buf\n" + end + + -- Setup the buffer + body = body .. generate_stackframe(buftype, bufsize, disposition, heap, def) .. + "\n" + + -- Any early initialization goes before we would fork for the just-after + -- tests, because they may want to skip the test based on some criteria + -- and we can't propagate that up very easily once we're forked. + local early_init = configurable(def, "early_init") + body = body .. (early_init or "") + if early_init then + body = body .. "\n" + end + + -- Fork off, iff we're testing some access past the end of the buffer. + if disposition > 0 then + body = body .. [[ + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); +]] + end + + local bufvar = "__stack.__buf" + if heap then + -- Buffer needs to be initialized because it's a heap allocation. + body = body .. "\t" .. bufvar .. " = malloc(__bufsz);\n" + end + + -- Non-early init happens just after the fork in the child, not the + -- monitor. This is used to setup any other buffers we may need, for + -- instance. + local extra_init = configurable(def, "init") + body = body .. (extra_init or "") + + if heap or extra_init then + body = body .. "\n" + end + + -- Setup the function call with arguments as described in the test + -- definition. + body = body .. "\t" .. func .. "(" + + for idx, arg in ipairs(def.arguments) do + if idx > 1 then + body = body .. ", " + end + + if arg == "__buf" then + if not heap and need_addr() then + body = body .. "&" + end + + body = body .. bufvar + else + local argname = arg + + if def.value_of then + argname = argname or def.value_of(arg) + end + + body = body .. argname + end + end + + body = body .. ");\n" + + -- Monitor stuff follows, for OOB access. + if disposition <= 0 then + goto skip + end + + body = body .. [[ + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +]] + +::skip:: + body = body .. "#undef BUF\n" + return write_test_boilerplate(fh, testname, body, def) +end + +-- main() +local tests +local tcat = assert(arg[1], "usage: generate-fortify-tests.lua <category>") +for k, defs in pairs(all_tests) do + if k == tcat then + tests = defs + break + end +end + +assert(tests, "category " .. tcat .. " not found") + +local fh = io.stdout +fh:write("/* @" .. "generated" .. " by `generate-fortify-tests.lua \"" .. + tcat .. "\"` */\n\n") +fh:write("#define _FORTIFY_SOURCE 2\n") +fh:write("#define TMPFILE_SIZE (1024 * 32)\n") + +fh:write("\n") +for _, inc in ipairs(includes) do + fh:write("#include <" .. inc .. ">\n") +end + +fh:write([[ + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +]]) + +if tcat == "unistd" then + fh:write("#define JAIL_HOSTNAME \"" .. hostname .. "\"\n") + fh:write("#define JAIL_DOMAINNAME \"" .. domainname .. "\"\n") + fh:write([[ +static void +dhost_jail(void) +{ + struct iovec iov[4]; + int jid; + + iov[0].iov_base = __DECONST(char *, "host.hostname"); + iov[0].iov_len = sizeof("host.hostname"); + iov[1].iov_base = __DECONST(char *, JAIL_HOSTNAME); + iov[1].iov_len = sizeof(JAIL_HOSTNAME); + iov[2].iov_base = __DECONST(char *, "host.domainname"); + iov[2].iov_len = sizeof("host.domainname"); + iov[3].iov_base = __DECONST(char *, JAIL_DOMAINNAME); + iov[3].iov_len = sizeof(JAIL_DOMAINNAME); + + jid = jail_set(iov, nitems(iov), JAIL_CREATE | JAIL_ATTACH); + ATF_REQUIRE_MSG(jid > 0, "Jail creation failed: %s", strerror(errno)); +} + +]]) +end + +for _, def in pairs(tests) do + local func = def.func + local function write_tests(heap) + -- Dispositions here are relative to the buffer size prescribed + -- by the test definition. + local dispositions = def.dispositions or { -1, 0, 1 } + + for _, disposition in ipairs(dispositions) do + tests_added[#tests_added + 1] = write_test(fh, func, disposition, heap, def) + end + end + + write_tests(false) + write_tests(true) +end + +fh:write("ATF_TP_ADD_TCS(tp)\n") +fh:write("{\n") +for idx = 1, #tests_added do + fh:write("\tATF_TP_ADD_TC(tp, " .. tests_added[idx] .. ");\n") +end +fh:write("\treturn (atf_no_error());\n") +fh:write("}\n") |