diff --git a/include/ssp/Makefile b/include/ssp/Makefile index d6e0e0698e36..e6c5a1e6c15e 100644 --- a/include/ssp/Makefile +++ b/include/ssp/Makefile @@ -1,5 +1,5 @@ -INCS= poll.h random.h ssp.h stdio.h stdlib.h string.h strings.h unistd.h +INCS= poll.h random.h ssp.h stdio.h stdlib.h string.h strings.h uio.h unistd.h INCS+= wchar.h INCSDIR= ${INCLUDEDIR}/ssp .include diff --git a/include/ssp/ssp.h b/include/ssp/ssp.h index 6ebc23288391..bdc14137d45b 100644 --- a/include/ssp/ssp.h +++ b/include/ssp/ssp.h @@ -1,109 +1,125 @@ /* $NetBSD: ssp.h,v 1.13 2015/09/03 20:43:47 plunky Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006, 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_SSP_H_ #define _SSP_SSP_H_ #include #if !defined(__cplusplus) # if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && \ (__OPTIMIZE__ > 0 || defined(__clang__)) # if _FORTIFY_SOURCE > 1 # define __SSP_FORTIFY_LEVEL 2 # else # define __SSP_FORTIFY_LEVEL 1 # endif # else # define __SSP_FORTIFY_LEVEL 0 # endif #else # define __SSP_FORTIFY_LEVEL 0 #endif #define __ssp_var(type) __CONCAT(__ssp_ ## type, __COUNTER__) /* __ssp_real is used by the implementation in libc */ #if __SSP_FORTIFY_LEVEL == 0 #define __ssp_real_(fun) fun #else #define __ssp_real_(fun) __ssp_real_ ## fun #endif #define __ssp_real(fun) __ssp_real_(fun) #define __ssp_inline static __inline __attribute__((__always_inline__)) #define __ssp_bos(ptr) __builtin_object_size(ptr, __SSP_FORTIFY_LEVEL > 1) #define __ssp_bos0(ptr) __builtin_object_size(ptr, 0) #define __ssp_check(buf, len, bos) \ if (bos(buf) != (size_t)-1 && (size_t)len > bos(buf)) \ __chk_fail() #define __ssp_redirect_raw_impl(rtype, fun, symbol, args) \ rtype __ssp_real_(fun) args __RENAME(symbol); \ __ssp_inline rtype fun args __RENAME(__ssp_protected_ ## fun); \ __ssp_inline rtype fun args #define __ssp_redirect_raw(rtype, fun, symbol, args, call, cond, bos, len) \ __ssp_redirect_raw_impl(rtype, fun, symbol, args) { \ if (cond) \ __ssp_check(__buf, len, bos); \ return __ssp_real_(fun) call; \ } #define __ssp_redirect(rtype, fun, args, call) \ __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos, __len) #define __ssp_redirect0(rtype, fun, args, call) \ __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0, __len) #include static inline int __ssp_overlap(const void *leftp, const void *rightp, __size_t sz) { __uintptr_t left = (__uintptr_t)leftp; __uintptr_t right = (__uintptr_t)rightp; if (left <= right) return (SIZE_MAX - sz < left || right < left + sz); return (SIZE_MAX - sz < right || left < right + sz); } +#include + __BEGIN_DECLS void __stack_chk_fail(void) __dead2; void __chk_fail(void) __dead2; __END_DECLS +__ssp_inline void +__ssp_check_iovec(const struct iovec *iov, int iovcnt) +{ + const size_t iovsz = __ssp_bos(iov); + + if (iovsz != (size_t)-1 && iovsz / sizeof(*iov) < (size_t)iovcnt) + __chk_fail(); + + for (int i = 0; i < iovcnt; i++) { + if (__ssp_bos(iov[i].iov_base) < iov[i].iov_len) + __chk_fail(); + } +} + #endif /* _SSP_SSP_H_ */ diff --git a/include/ssp/uio.h b/include/ssp/uio.h new file mode 100644 index 000000000000..adf1dcbb3d67 --- /dev/null +++ b/include/ssp/uio.h @@ -0,0 +1,53 @@ +/*- + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ +#ifndef _SSP_UIO_H_ +#define _SSP_UIO_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__BEGIN_DECLS + +__ssp_redirect_raw_impl(ssize_t, readv, readv, + (int fd, const struct iovec *iov, int iovcnt)) +{ + __ssp_check_iovec(iov, iovcnt); + return (__ssp_real(readv)(fd, iov, iovcnt)); +} + +__ssp_redirect_raw_impl(ssize_t, preadv, preadv, + (int fd, const struct iovec *iov, int iovcnt, off_t offset)) +{ + __ssp_check_iovec(iov, iovcnt); + return (__ssp_real(preadv)(fd, iov, iovcnt, offset)); +} + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_UIO_H_ */ diff --git a/lib/libc/sys/readv.c b/lib/libc/sys/readv.c index 78a529254fa0..d58dba1fc47e 100644 --- a/lib/libc/sys/readv.c +++ b/lib/libc/sys/readv.c @@ -1,45 +1,46 @@ /* * Copyright (c) 2014 The FreeBSD Foundation. * * Portions of this software were developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. */ #include #include #include #include +#include #include "libc_private.h" __weak_reference(__sys_readv, __readv); #pragma weak readv ssize_t -readv(int fd, const struct iovec *iov, int iovcnt) +__ssp_real(readv)(int fd, const struct iovec *iov, int iovcnt) { return (INTERPOS_SYS(readv, fd, iov, iovcnt)); } diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile index 87c491d9cf2f..7aa9212b97a8 100644 --- a/lib/libc/tests/secure/Makefile +++ b/lib/libc/tests/secure/Makefile @@ -1,27 +1,28 @@ .include TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} # sys/ headers FORTIFY_TCATS+= random +FORTIFY_TCATS+= uio # non-sys/ headers FORTIFY_TCATS+= poll 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. generate-tests: .PHONY .for tcat in ${FORTIFY_TCATS} ATF_TESTS_C+= fortify_${tcat}_test generate-tests: generate-tests-${tcat} generate-tests-${tcat}: .PHONY ${.CURDIR}/generate-fortify-tests.lua ${tcat} > ${.CURDIR}/fortify_${tcat}_test.c .endfor .include diff --git a/lib/libc/tests/secure/fortify_poll_test.c b/lib/libc/tests/secure/fortify_poll_test.c index 2723052ac501..83c0f68b0daa 100644 --- a/lib/libc/tests/secure/fortify_poll_test.c +++ b/lib/libc/tests/secure/fortify_poll_test.c @@ -1,533 +1,534 @@ /* @generated by `generate-fortify-tests.lua "poll"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(poll_before_end); 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_WITHOUT_HEAD(poll_end); 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_WITHOUT_HEAD(poll_after_end); 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_WITHOUT_HEAD(poll_heap_before_end); 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_WITHOUT_HEAD(poll_heap_end); 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_WITHOUT_HEAD(poll_heap_after_end); 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_WITHOUT_HEAD(ppoll_before_end); 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_WITHOUT_HEAD(ppoll_end); 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_WITHOUT_HEAD(ppoll_after_end); 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_WITHOUT_HEAD(ppoll_heap_before_end); 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_WITHOUT_HEAD(ppoll_heap_end); 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_WITHOUT_HEAD(ppoll_heap_after_end); 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 index b89410a702d0..1eb18cfcaaf4 100644 --- a/lib/libc/tests/secure/fortify_random_test.c +++ b/lib/libc/tests/secure/fortify_random_test.c @@ -1,253 +1,254 @@ /* @generated by `generate-fortify-tests.lua "random"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(getrandom_before_end); 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_WITHOUT_HEAD(getrandom_end); 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_WITHOUT_HEAD(getrandom_heap_before_end); 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_WITHOUT_HEAD(getrandom_heap_end); 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_WITHOUT_HEAD(getrandom_heap_after_end); 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_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c index a19bfebba1bb..75f81c0a0750 100644 --- a/lib/libc/tests/secure/fortify_stdio_test.c +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -1,1376 +1,1377 @@ /* @generated by `generate-fortify-tests.lua "stdio"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(ctermid_before_end); 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_WITHOUT_HEAD(ctermid_end); 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_WITHOUT_HEAD(ctermid_heap_before_end); 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_WITHOUT_HEAD(ctermid_heap_end); 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_WITHOUT_HEAD(ctermid_heap_after_end); 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_WITHOUT_HEAD(ctermid_r_before_end); 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_WITHOUT_HEAD(ctermid_r_end); 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_WITHOUT_HEAD(ctermid_r_heap_before_end); 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_WITHOUT_HEAD(ctermid_r_heap_end); 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_WITHOUT_HEAD(ctermid_r_heap_after_end); 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_WITHOUT_HEAD(fread_before_end); 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_WITHOUT_HEAD(fread_end); 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_WITHOUT_HEAD(fread_heap_before_end); 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_WITHOUT_HEAD(fread_heap_end); 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_WITHOUT_HEAD(fread_heap_after_end); 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_WITHOUT_HEAD(fread_unlocked_before_end); 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_WITHOUT_HEAD(fread_unlocked_end); 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_WITHOUT_HEAD(fread_unlocked_heap_before_end); 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_WITHOUT_HEAD(fread_unlocked_heap_end); 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_WITHOUT_HEAD(fread_unlocked_heap_after_end); 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_WITHOUT_HEAD(gets_s_before_end); 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_WITHOUT_HEAD(gets_s_end); 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_WITHOUT_HEAD(gets_s_heap_before_end); 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_WITHOUT_HEAD(gets_s_heap_end); 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_WITHOUT_HEAD(gets_s_heap_after_end); 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_WITHOUT_HEAD(sprintf_before_end); 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_WITHOUT_HEAD(sprintf_end); 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_WITHOUT_HEAD(sprintf_heap_before_end); 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_WITHOUT_HEAD(sprintf_heap_end); 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_WITHOUT_HEAD(sprintf_heap_after_end); 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_WITHOUT_HEAD(snprintf_before_end); 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_WITHOUT_HEAD(snprintf_end); 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_WITHOUT_HEAD(snprintf_heap_before_end); 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_WITHOUT_HEAD(snprintf_heap_end); 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_WITHOUT_HEAD(snprintf_heap_after_end); 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_WITHOUT_HEAD(tmpnam_before_end); 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_WITHOUT_HEAD(tmpnam_end); 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_WITHOUT_HEAD(tmpnam_heap_before_end); 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_WITHOUT_HEAD(tmpnam_heap_end); 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_WITHOUT_HEAD(tmpnam_heap_after_end); 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_WITHOUT_HEAD(fgets_before_end); 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_WITHOUT_HEAD(fgets_end); 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_WITHOUT_HEAD(fgets_heap_before_end); 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_WITHOUT_HEAD(fgets_heap_end); 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_WITHOUT_HEAD(fgets_heap_after_end); 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 index 47f4157b5a01..8556e1110156 100644 --- a/lib/libc/tests/secure/fortify_stdlib_test.c +++ b/lib/libc/tests/secure/fortify_stdlib_test.c @@ -1,385 +1,386 @@ /* @generated by `generate-fortify-tests.lua "stdlib"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(arc4random_buf_before_end); 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_WITHOUT_HEAD(arc4random_buf_end); 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_WITHOUT_HEAD(arc4random_buf_heap_before_end); 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_WITHOUT_HEAD(arc4random_buf_heap_end); 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_WITHOUT_HEAD(arc4random_buf_heap_after_end); 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_WITHOUT_HEAD(realpath_before_end); 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_WITHOUT_HEAD(realpath_end); 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_WITHOUT_HEAD(realpath_heap_before_end); 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_WITHOUT_HEAD(realpath_heap_end); 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_WITHOUT_HEAD(realpath_heap_after_end); 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, 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 index 6a4f08705602..70f247b09e39 100644 --- a/lib/libc/tests/secure/fortify_string_test.c +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -1,1896 +1,1897 @@ /* @generated by `generate-fortify-tests.lua "string"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(memcpy_before_end); 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_WITHOUT_HEAD(memcpy_end); 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_WITHOUT_HEAD(memcpy_heap_before_end); 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_WITHOUT_HEAD(memcpy_heap_end); 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_WITHOUT_HEAD(memcpy_heap_after_end); 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_WITHOUT_HEAD(mempcpy_before_end); 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_WITHOUT_HEAD(mempcpy_end); 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_WITHOUT_HEAD(mempcpy_heap_before_end); 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_WITHOUT_HEAD(mempcpy_heap_end); 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_WITHOUT_HEAD(mempcpy_heap_after_end); 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_WITHOUT_HEAD(memmove_before_end); 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_WITHOUT_HEAD(memmove_end); 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_WITHOUT_HEAD(memmove_heap_before_end); 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_WITHOUT_HEAD(memmove_heap_end); 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_WITHOUT_HEAD(memmove_heap_after_end); 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_WITHOUT_HEAD(memset_before_end); 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_WITHOUT_HEAD(memset_end); 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_WITHOUT_HEAD(memset_heap_before_end); 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_WITHOUT_HEAD(memset_heap_end); 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_WITHOUT_HEAD(memset_heap_after_end); 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_WITHOUT_HEAD(stpcpy_before_end); 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_WITHOUT_HEAD(stpcpy_end); 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_WITHOUT_HEAD(stpcpy_heap_before_end); 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_WITHOUT_HEAD(stpcpy_heap_end); 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_WITHOUT_HEAD(stpcpy_heap_after_end); 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_WITHOUT_HEAD(stpncpy_before_end); 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_WITHOUT_HEAD(stpncpy_end); 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_WITHOUT_HEAD(stpncpy_heap_before_end); 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_WITHOUT_HEAD(stpncpy_heap_end); 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_WITHOUT_HEAD(stpncpy_heap_after_end); 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_WITHOUT_HEAD(strcat_before_end); 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_WITHOUT_HEAD(strcat_end); 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_WITHOUT_HEAD(strcat_heap_before_end); 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_WITHOUT_HEAD(strcat_heap_end); 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_WITHOUT_HEAD(strcat_heap_after_end); 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_WITHOUT_HEAD(strlcat_before_end); 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_WITHOUT_HEAD(strlcat_end); 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_WITHOUT_HEAD(strlcat_heap_before_end); 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_WITHOUT_HEAD(strlcat_heap_end); 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_WITHOUT_HEAD(strlcat_heap_after_end); 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_WITHOUT_HEAD(strncat_before_end); 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_WITHOUT_HEAD(strncat_end); 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_WITHOUT_HEAD(strncat_heap_before_end); 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_WITHOUT_HEAD(strncat_heap_end); 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_WITHOUT_HEAD(strncat_heap_after_end); 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_WITHOUT_HEAD(strcpy_before_end); 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_WITHOUT_HEAD(strcpy_end); 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_WITHOUT_HEAD(strcpy_heap_before_end); 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_WITHOUT_HEAD(strcpy_heap_end); 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_WITHOUT_HEAD(strcpy_heap_after_end); 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_WITHOUT_HEAD(strlcpy_before_end); 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_WITHOUT_HEAD(strlcpy_end); 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_WITHOUT_HEAD(strlcpy_heap_before_end); 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_WITHOUT_HEAD(strlcpy_heap_end); 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_WITHOUT_HEAD(strlcpy_heap_after_end); 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_WITHOUT_HEAD(strncpy_before_end); 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_WITHOUT_HEAD(strncpy_end); 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_WITHOUT_HEAD(strncpy_heap_before_end); 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_WITHOUT_HEAD(strncpy_heap_end); 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_WITHOUT_HEAD(strncpy_heap_after_end); 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, 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 index ec6340e77f74..e6a8ea0291de 100644 --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -1,522 +1,523 @@ /* @generated by `generate-fortify-tests.lua "strings"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(bcopy_before_end); 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_WITHOUT_HEAD(bcopy_end); 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_WITHOUT_HEAD(bcopy_heap_before_end); 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_WITHOUT_HEAD(bcopy_heap_end); 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_WITHOUT_HEAD(bcopy_heap_after_end); 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_WITHOUT_HEAD(bzero_before_end); 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_WITHOUT_HEAD(bzero_end); 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_WITHOUT_HEAD(bzero_heap_before_end); 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_WITHOUT_HEAD(bzero_heap_end); 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_WITHOUT_HEAD(bzero_heap_after_end); 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_WITHOUT_HEAD(explicit_bzero_before_end); 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_WITHOUT_HEAD(explicit_bzero_end); 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_WITHOUT_HEAD(explicit_bzero_heap_before_end); 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_WITHOUT_HEAD(explicit_bzero_heap_end); 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_WITHOUT_HEAD(explicit_bzero_heap_after_end); 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..56d7cf5d9a84 --- /dev/null +++ b/lib/libc/tests/secure/fortify_uio_test.c @@ -0,0 +1,804 @@ +/* @generated by `generate-fortify-tests.lua "uio"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + +/* + * 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_WITHOUT_HEAD(readv_before_end); +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_WITHOUT_HEAD(readv_end); +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_WITHOUT_HEAD(readv_after_end); +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_WITHOUT_HEAD(readv_heap_before_end); +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_WITHOUT_HEAD(readv_heap_end); +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_WITHOUT_HEAD(readv_heap_after_end); +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_WITHOUT_HEAD(readv_iov_before_end); +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_WITHOUT_HEAD(readv_iov_end); +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_WITHOUT_HEAD(readv_iov_heap_before_end); +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_WITHOUT_HEAD(readv_iov_heap_end); +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_WITHOUT_HEAD(readv_iov_heap_after_end); +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_WITHOUT_HEAD(preadv_before_end); +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_WITHOUT_HEAD(preadv_end); +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_WITHOUT_HEAD(preadv_after_end); +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_WITHOUT_HEAD(preadv_heap_before_end); +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_WITHOUT_HEAD(preadv_heap_end); +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_WITHOUT_HEAD(preadv_heap_after_end); +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_WITHOUT_HEAD(preadv_iov_before_end); +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_WITHOUT_HEAD(preadv_iov_end); +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_WITHOUT_HEAD(preadv_iov_heap_before_end); +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_WITHOUT_HEAD(preadv_iov_heap_end); +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_WITHOUT_HEAD(preadv_iov_heap_after_end); +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 index fa478955283e..7a91d3b06c75 100644 --- a/lib/libc/tests/secure/fortify_unistd_test.c +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -1,1970 +1,1971 @@ /* @generated by `generate-fortify-tests.lua "unistd"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(getcwd_before_end); 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_WITHOUT_HEAD(getcwd_end); 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_WITHOUT_HEAD(getcwd_heap_before_end); 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_WITHOUT_HEAD(getcwd_heap_end); 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_WITHOUT_HEAD(getcwd_heap_after_end); 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_WITHOUT_HEAD(getgrouplist_before_end); 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_WITHOUT_HEAD(getgrouplist_end); 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_WITHOUT_HEAD(getgrouplist_heap_before_end); 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_WITHOUT_HEAD(getgrouplist_heap_end); 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_WITHOUT_HEAD(getgrouplist_heap_after_end); 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_WITHOUT_HEAD(getgroups_before_end); 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_WITHOUT_HEAD(getgroups_end); 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_WITHOUT_HEAD(getgroups_heap_before_end); 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_WITHOUT_HEAD(getgroups_heap_end); 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_WITHOUT_HEAD(getgroups_heap_after_end); 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_WITHOUT_HEAD(getloginclass_before_end); 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_WITHOUT_HEAD(getloginclass_end); 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_WITHOUT_HEAD(getloginclass_heap_before_end); 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_WITHOUT_HEAD(getloginclass_heap_end); 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_WITHOUT_HEAD(getloginclass_heap_after_end); 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_WITHOUT_HEAD(pread_before_end); 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_WITHOUT_HEAD(pread_end); 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_WITHOUT_HEAD(pread_heap_before_end); 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_WITHOUT_HEAD(pread_heap_end); 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_WITHOUT_HEAD(pread_heap_after_end); 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_WITHOUT_HEAD(read_before_end); 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_WITHOUT_HEAD(read_end); 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_WITHOUT_HEAD(read_heap_before_end); 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_WITHOUT_HEAD(read_heap_end); 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_WITHOUT_HEAD(read_heap_after_end); 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_WITHOUT_HEAD(readlink_before_end); 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_WITHOUT_HEAD(readlink_end); 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_WITHOUT_HEAD(readlink_heap_before_end); 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_WITHOUT_HEAD(readlink_heap_end); 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_WITHOUT_HEAD(readlink_heap_after_end); 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_WITHOUT_HEAD(readlinkat_before_end); 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_WITHOUT_HEAD(readlinkat_end); 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_WITHOUT_HEAD(readlinkat_heap_before_end); 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_WITHOUT_HEAD(readlinkat_heap_end); 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_WITHOUT_HEAD(readlinkat_heap_after_end); 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_WITHOUT_HEAD(getdomainname_before_end); ATF_TC_BODY(getdomainname_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __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; char sysdomain[256]; (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); getdomainname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getdomainname_end); ATF_TC_BODY(getdomainname_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __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; char sysdomain[256]; (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); getdomainname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getdomainname_heap_before_end); 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) * (4); const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; char sysdomain[256]; (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); __stack.__buf = malloc(__bufsz); getdomainname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getdomainname_heap_end); 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) * (4); const size_t __len = 4; const size_t __idx __unused = __len - 1; char sysdomain[256]; (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); __stack.__buf = malloc(__bufsz); getdomainname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getdomainname_heap_after_end); 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) * (4); const size_t __len = 4 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char sysdomain[256]; (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); __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_WITHOUT_HEAD(getentropy_before_end); 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_WITHOUT_HEAD(getentropy_end); 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_WITHOUT_HEAD(getentropy_heap_before_end); 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_WITHOUT_HEAD(getentropy_heap_end); 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_WITHOUT_HEAD(getentropy_heap_after_end); 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_WITHOUT_HEAD(gethostname_before_end); ATF_TC_BODY(gethostname_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __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; char syshost[256]; int error; error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); gethostname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(gethostname_end); ATF_TC_BODY(gethostname_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __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; char syshost[256]; int error; error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); gethostname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(gethostname_heap_before_end); 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) * (4); const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; char syshost[256]; int error; error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); __stack.__buf = malloc(__bufsz); gethostname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(gethostname_heap_end); 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) * (4); const size_t __len = 4; const size_t __idx __unused = __len - 1; char syshost[256]; int error; error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); __stack.__buf = malloc(__bufsz); gethostname(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(gethostname_heap_after_end); 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) * (4); const size_t __len = 4 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char syshost[256]; int error; error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); __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_WITHOUT_HEAD(getlogin_r_before_end); 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_WITHOUT_HEAD(getlogin_r_end); 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_WITHOUT_HEAD(getlogin_r_heap_before_end); 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_WITHOUT_HEAD(getlogin_r_heap_end); 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_WITHOUT_HEAD(getlogin_r_heap_after_end); 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_WITHOUT_HEAD(ttyname_r_before_end); 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_WITHOUT_HEAD(ttyname_r_end); 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_WITHOUT_HEAD(ttyname_r_heap_before_end); 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_WITHOUT_HEAD(ttyname_r_heap_end); 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_WITHOUT_HEAD(ttyname_r_heap_after_end); 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 index cd09e5dac93c..8c5e0782c65a 100644 --- a/lib/libc/tests/secure/fortify_wchar_test.c +++ b/lib/libc/tests/secure/fortify_wchar_test.c @@ -1,1896 +1,1897 @@ /* @generated by `generate-fortify-tests.lua "wchar"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); } /* * 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_WITHOUT_HEAD(wmemcpy_before_end); 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_WITHOUT_HEAD(wmemcpy_end); 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_WITHOUT_HEAD(wmemcpy_heap_before_end); 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_WITHOUT_HEAD(wmemcpy_heap_end); 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_WITHOUT_HEAD(wmemcpy_heap_after_end); 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_WITHOUT_HEAD(wmempcpy_before_end); 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_WITHOUT_HEAD(wmempcpy_end); 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_WITHOUT_HEAD(wmempcpy_heap_before_end); 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_WITHOUT_HEAD(wmempcpy_heap_end); 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_WITHOUT_HEAD(wmempcpy_heap_after_end); 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_WITHOUT_HEAD(wmemmove_before_end); 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_WITHOUT_HEAD(wmemmove_end); 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_WITHOUT_HEAD(wmemmove_heap_before_end); 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_WITHOUT_HEAD(wmemmove_heap_end); 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_WITHOUT_HEAD(wmemmove_heap_after_end); 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_WITHOUT_HEAD(wmemset_before_end); 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_WITHOUT_HEAD(wmemset_end); 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_WITHOUT_HEAD(wmemset_heap_before_end); 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_WITHOUT_HEAD(wmemset_heap_end); 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_WITHOUT_HEAD(wmemset_heap_after_end); 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_WITHOUT_HEAD(wcpcpy_before_end); 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_WITHOUT_HEAD(wcpcpy_end); 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_WITHOUT_HEAD(wcpcpy_heap_before_end); 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_WITHOUT_HEAD(wcpcpy_heap_end); 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_WITHOUT_HEAD(wcpcpy_heap_after_end); 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_WITHOUT_HEAD(wcpncpy_before_end); 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_WITHOUT_HEAD(wcpncpy_end); 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_WITHOUT_HEAD(wcpncpy_heap_before_end); 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_WITHOUT_HEAD(wcpncpy_heap_end); 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_WITHOUT_HEAD(wcpncpy_heap_after_end); 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_WITHOUT_HEAD(wcscat_before_end); 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_WITHOUT_HEAD(wcscat_end); 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_WITHOUT_HEAD(wcscat_heap_before_end); 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_WITHOUT_HEAD(wcscat_heap_end); 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_WITHOUT_HEAD(wcscat_heap_after_end); 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_WITHOUT_HEAD(wcslcat_before_end); 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_WITHOUT_HEAD(wcslcat_end); 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_WITHOUT_HEAD(wcslcat_heap_before_end); 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_WITHOUT_HEAD(wcslcat_heap_end); 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_WITHOUT_HEAD(wcslcat_heap_after_end); 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_WITHOUT_HEAD(wcsncat_before_end); 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_WITHOUT_HEAD(wcsncat_end); 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_WITHOUT_HEAD(wcsncat_heap_before_end); 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_WITHOUT_HEAD(wcsncat_heap_end); 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_WITHOUT_HEAD(wcsncat_heap_after_end); 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_WITHOUT_HEAD(wcscpy_before_end); 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_WITHOUT_HEAD(wcscpy_end); 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_WITHOUT_HEAD(wcscpy_heap_before_end); 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_WITHOUT_HEAD(wcscpy_heap_end); 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_WITHOUT_HEAD(wcscpy_heap_after_end); 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_WITHOUT_HEAD(wcslcpy_before_end); 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_WITHOUT_HEAD(wcslcpy_end); 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_WITHOUT_HEAD(wcslcpy_heap_before_end); 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_WITHOUT_HEAD(wcslcpy_heap_end); 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_WITHOUT_HEAD(wcslcpy_heap_after_end); 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_WITHOUT_HEAD(wcsncpy_before_end); 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_WITHOUT_HEAD(wcsncpy_end); 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_WITHOUT_HEAD(wcsncpy_heap_before_end); 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_WITHOUT_HEAD(wcsncpy_heap_end); 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_WITHOUT_HEAD(wcsncpy_heap_after_end); 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 index 259c9a7825d9..23b33acb757b 100755 --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -1,1194 +1,1254 @@ #!/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/random.h", "sys/resource.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 = {} -- 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 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 = { -- { func = "getrandom", arguments = { "__buf", "__len", "0", }, exclude = excludes_stack_overflow, }, }, + uio = { + -- + { + 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 = { -- { 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, }, }, stdio = { -- { 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 = { -- { func = "arc4random_buf", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, }, { func = "realpath", bufsize = "PATH_MAX", arguments = { "\".\"", "__buf", }, exclude = excludes_stack_overflow, }, }, string = { -- { 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 = "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 = { -- { 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 = { -- { 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 = "4", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tchar sysdomain[256];\n", early_init = [[ (void)getdomainname(sysdomain, __len); if (strlen(sysdomain) <= __len) atf_tc_skip("domain name too short for testing"); ]] }, { func = "getentropy", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, }, { func = "gethostname", bufsize = "4", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, stackvars = [[ char syshost[256]; int error; ]], early_init = [[ error = gethostname(syshost, __len); if (error != 0 || strlen(syshost) <= __len) atf_tc_skip("hostname too short for testing"); ]] }, { 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 = { -- { 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) fh:write("ATF_TC_WITHOUT_HEAD(" .. name .. ");\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, disposition) -- 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(def) 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(def) local bufsize_offset = len_offset(not uses_len, disposition) 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(buftype) 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(buftype) 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) end -- main() local tests local tcat = assert(arg[1], "usage: generate-fortify-tests.lua ") 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); } /* * 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); } ]]) 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") diff --git a/sys/sys/uio.h b/sys/sys/uio.h index 42ab0cda8e38..1c9d2d39cf57 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -1,113 +1,117 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1982, 1986, 1993, 1994 * The Regents of the University of California. All rights reserved. * * 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. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef _SYS_UIO_H_ #define _SYS_UIO_H_ #include #include #include #include #ifndef _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #define _SSIZE_T_DECLARED #endif #ifndef _OFF_T_DECLARED typedef __off_t off_t; #define _OFF_T_DECLARED #endif #ifdef _KERNEL struct uio { struct iovec *uio_iov; /* scatter/gather list */ int uio_iovcnt; /* length of scatter/gather list */ off_t uio_offset; /* offset in target object */ ssize_t uio_resid; /* remaining bytes to process */ enum uio_seg uio_segflg; /* address space */ enum uio_rw uio_rw; /* operation */ struct thread *uio_td; /* owner */ }; /* * Limits * * N.B.: UIO_MAXIOV must be no less than IOV_MAX from * which in turn must be no less than _XOPEN_IOV_MAX from . If * we ever make this tunable (probably pointless), then IOV_MAX should be * removed from and applications would be expected to use * sysconf(3) to find out the correct value, or else assume the worst * (_XOPEN_IOV_MAX). Perhaps UIO_MAXIOV should be simply defined as * IOV_MAX. */ #define UIO_MAXIOV 1024 /* max 1K of iov's */ struct vm_object; struct vm_page; struct bus_dma_segment; struct uio *allocuio(u_int iovcnt); void freeuio(struct uio *uio); struct uio *cloneuio(struct uio *uiop); int copyiniov(const struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error); int copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop); int copyout_map(struct thread *td, vm_offset_t *addr, size_t sz); int copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz); int physcopyin(void *src, vm_paddr_t dst, size_t len); int physcopyout(vm_paddr_t src, void *dst, size_t len); int physcopyin_vlist(struct bus_dma_segment *src, off_t offset, vm_paddr_t dst, size_t len); int physcopyout_vlist(vm_paddr_t src, struct bus_dma_segment *dst, off_t offset, size_t len); int uiomove(void *cp, int n, struct uio *uio); int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n, struct uio *uio); int uiomove_nofault(void *cp, int n, struct uio *uio); int uiomove_object(struct vm_object *obj, off_t obj_size, struct uio *uio); #else /* !_KERNEL */ +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS ssize_t readv(int, const struct iovec *, int); ssize_t writev(int, const struct iovec *, int); #if __BSD_VISIBLE ssize_t preadv(int, const struct iovec *, int, off_t); ssize_t pwritev(int, const struct iovec *, int, off_t); #endif __END_DECLS #endif /* _KERNEL */ #endif /* !_SYS_UIO_H_ */