diff --git a/include/ssp/Makefile b/include/ssp/Makefile --- a/include/ssp/Makefile +++ b/include/ssp/Makefile @@ -1,4 +1,4 @@ -INCS= ssp.h stdio.h string.h strings.h unistd.h +INCS= poll.h ssp.h stdio.h string.h strings.h unistd.h INCSDIR= ${INCLUDEDIR}/ssp .include diff --git a/include/ssp/poll.h b/include/ssp/poll.h new file mode 100644 --- /dev/null +++ b/include/ssp/poll.h @@ -0,0 +1,62 @@ +/*- + * 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_POLL_H_ +#define _SSP_POLL_H_ + +#include + +#if __SSP_FORTIFY_LEVEL > 0 + +__BEGIN_DECLS + +__ssp_redirect_raw_impl(int, poll, poll, + (struct pollfd fds[], nfds_t nfds, int timeout)) +{ + + if (__ssp_bos(fds) / sizeof(fds[0]) < nfds) + __chk_fail(); + + return (__ssp_real(poll)(fds, nfds, timeout)); +} + + +__ssp_redirect_raw_impl(int, ppoll, ppoll, + (struct pollfd fds[], nfds_t nfds, + const struct timespec *__restrict timeout, + const sigset_t *__restrict newsigmask)) +{ + + if (__ssp_bos(fds) / sizeof(fds[0]) < nfds) + __chk_fail(); + + return (__ssp_real(ppoll)(fds, nfds, timeout, newsigmask)); +} + +__END_DECLS + +#endif /* __SSP_FORTIFY_LEVEL > 0 */ +#endif /* _SSP_POLL_H_ */ diff --git a/lib/libc/sys/poll.c b/lib/libc/sys/poll.c --- a/lib/libc/sys/poll.c +++ b/lib/libc/sys/poll.c @@ -31,13 +31,14 @@ #include #include +#include #include "libc_private.h" __weak_reference(__sys_poll, __poll); -#pragma weak poll +#pragma weak __ssp_real(poll) int -poll(struct pollfd pfd[], nfds_t nfds, int timeout) +__ssp_real(poll)(struct pollfd pfd[], nfds_t nfds, int timeout) { return (INTERPOS_SYS(poll, pfd, nfds, timeout)); } diff --git a/lib/libc/sys/ppoll.c b/lib/libc/sys/ppoll.c --- a/lib/libc/sys/ppoll.c +++ b/lib/libc/sys/ppoll.c @@ -31,14 +31,16 @@ #include #include +#include #include "libc_private.h" __weak_reference(__sys_ppoll, __ppoll); -#pragma weak ppoll +#pragma weak __ssp_real(ppoll) int -ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec *__restrict - timeout, const sigset_t *__restrict newsigmask) +__ssp_real(ppoll)(struct pollfd pfd[], nfds_t nfds, + const struct timespec *__restrict timeout, + const sigset_t *__restrict newsigmask) { return (INTERPOS_SYS(ppoll, pfd, nfds, timeout, newsigmask)); } diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile --- a/lib/libc/tests/secure/Makefile +++ b/lib/libc/tests/secure/Makefile @@ -2,6 +2,7 @@ TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} +FORTIFY_TCATS+= poll FORTIFY_TCATS+= stdio FORTIFY_TCATS+= string FORTIFY_TCATS+= strings diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_poll_test.c copy from lib/libc/tests/secure/fortify_strings_test.c copy to lib/libc/tests/secure/fortify_poll_test.c --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_poll_test.c @@ -1,4 +1,4 @@ -/* @generated by `generate-fortify-tests.lua "strings"` */ +/* @generated by `generate-fortify-tests.lua "poll"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -112,101 +113,64 @@ close(fd); } -ATF_TC_WITHOUT_HEAD(bcopy_before_end); -ATF_TC_BODY(bcopy_before_end, tc) +ATF_TC_WITHOUT_HEAD(poll_before_end); +ATF_TC_BODY(poll_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[42]; + struct pollfd __buf[4]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); - const size_t __len = 42 - 1; + const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; - char src[__len + 10]; - bcopy(src, __stack.__buf, __len); + 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(bcopy_end); -ATF_TC_BODY(bcopy_end, tc) +ATF_TC_WITHOUT_HEAD(poll_end); +ATF_TC_BODY(poll_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[42]; + struct pollfd __buf[4]; 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 __len = 4; const size_t __idx __unused = __len - 1; - char src[__len + 10]; - __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } - bcopy(src, __stack.__buf, __len); + poll(__stack.__buf, __len, 0); #undef BUF } -ATF_TC_WITHOUT_HEAD(bcopy_heap_after_end); -ATF_TC_BODY(bcopy_heap_after_end, tc) +ATF_TC_WITHOUT_HEAD(poll_after_end); +ATF_TC_BODY(poll_after_end, tc) { -#define BUF __stack.__buf +#define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + struct pollfd __buf[4]; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42 + 1; + 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; - char src[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); @@ -215,9 +179,11 @@ /* Child */ disable_coredumps(); - __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } - bcopy(src, __stack.__buf, __len); + poll(__stack.__buf, __len, 0); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: @@ -244,93 +210,63 @@ } -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) +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; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42 - 1; + 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; + } - bzero(__stack.__buf, __len); + poll(__stack.__buf, __len, 0); #undef BUF } -ATF_TC_WITHOUT_HEAD(bzero_heap_end); -ATF_TC_BODY(bzero_heap_end, tc) +ATF_TC_WITHOUT_HEAD(poll_heap_end); +ATF_TC_BODY(poll_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42; + 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; + } - bzero(__stack.__buf, __len); + poll(__stack.__buf, __len, 0); #undef BUF } -ATF_TC_WITHOUT_HEAD(bzero_heap_after_end); -ATF_TC_BODY(bzero_heap_after_end, tc) +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; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42 + 1; + 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; @@ -343,8 +279,11 @@ /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } - bzero(__stack.__buf, __len); + poll(__stack.__buf, __len, 0); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: @@ -371,96 +310,169 @@ } -ATF_TC_WITHOUT_HEAD(explicit_bzero_before_end); -ATF_TC_BODY(explicit_bzero_before_end, tc) +ATF_TC_WITHOUT_HEAD(ppoll_before_end); +ATF_TC_BODY(ppoll_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[42]; + struct pollfd __buf[4]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); - const size_t __len = 42 - 1; + 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; + } - explicit_bzero(__stack.__buf, __len); + ppoll(__stack.__buf, __len, &tv, NULL); #undef BUF } -ATF_TC_WITHOUT_HEAD(explicit_bzero_end); -ATF_TC_BODY(explicit_bzero_end, tc) +ATF_TC_WITHOUT_HEAD(ppoll_end); +ATF_TC_BODY(ppoll_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[42]; + struct pollfd __buf[4]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); - const size_t __len = 42; + 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; - explicit_bzero(__stack.__buf, __len); + /* 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(explicit_bzero_heap_before_end); -ATF_TC_BODY(explicit_bzero_heap_before_end, tc) +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; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42 - 1; + 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; + } - explicit_bzero(__stack.__buf, __len); + ppoll(__stack.__buf, __len, &tv, NULL); #undef BUF } -ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_end); -ATF_TC_BODY(explicit_bzero_heap_end, tc) +ATF_TC_WITHOUT_HEAD(ppoll_heap_end); +ATF_TC_BODY(ppoll_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42; + 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; + } - explicit_bzero(__stack.__buf, __len); + ppoll(__stack.__buf, __len, &tv, NULL); #undef BUF } -ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_after_end); -ATF_TC_BODY(explicit_bzero_heap_after_end, tc) +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; - unsigned char * __buf; + struct pollfd * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); - const size_t __len = 42 + 1; + 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); @@ -470,8 +482,11 @@ /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); + for (size_t i = 0; i < howmany(__bufsz, sizeof(struct pollfd)); i++) { + __stack.__buf[i].fd = -1; + } - explicit_bzero(__stack.__buf, __len); + ppoll(__stack.__buf, __len, &tv, NULL); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: @@ -500,20 +515,17 @@ 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); + 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_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c --- a/lib/libc/tests/secure/fortify_stdio_test.c +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c --- a/lib/libc/tests/secure/fortify_string_test.c +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c --- a/lib/libc/tests/secure/fortify_unistd_test.c +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -69,6 +69,7 @@ "errno.h", "fcntl.h", "limits.h", + "poll.h", "signal.h", "stdio.h", "stdlib.h", @@ -90,6 +91,12 @@ 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); @@ -132,6 +139,33 @@ -- circumstances it's useful to use a different type (e.g., for alignment -- requirements). local all_tests = { + 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 = { -- { diff --git a/sys/sys/poll.h b/sys/sys/poll.h --- a/sys/sys/poll.h +++ b/sys/sys/poll.h @@ -109,6 +109,10 @@ #endif +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout); #if __BSD_VISIBLE