git: 2aba0eea3fff - main - include: ssp: fortify <sys/select.h>
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 13 Jul 2024 05:23:07 UTC
The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=2aba0eea3ffffce74f9d8df20e0aaf49ea6d76c3 commit 2aba0eea3ffffce74f9d8df20e0aaf49ea6d76c3 Author: Kyle Evans <kevans@FreeBSD.org> AuthorDate: 2024-07-13 05:16:12 +0000 Commit: Kyle Evans <kevans@FreeBSD.org> CommitDate: 2024-07-13 05:16:25 +0000 include: ssp: fortify <sys/select.h> Notably sanity check indices passed to the FD_*() macros against the size of the fd_set itself. Reviewed by: markj Sponsored by: Klara, Inc. Sponsored by: Stormshield Differential Revision: https://reviews.freebsd.org/D45685 --- lib/libc/tests/secure/Makefile | 1 + lib/libc/tests/secure/fortify_poll_test.c | 1 + lib/libc/tests/secure/fortify_random_test.c | 1 + lib/libc/tests/secure/fortify_select_test.c | 669 +++++++++++++++++++++++ lib/libc/tests/secure/fortify_stdio_test.c | 1 + lib/libc/tests/secure/fortify_stdlib_test.c | 1 + lib/libc/tests/secure/fortify_string_test.c | 1 + lib/libc/tests/secure/fortify_strings_test.c | 1 + lib/libc/tests/secure/fortify_uio_test.c | 1 + lib/libc/tests/secure/fortify_unistd_test.c | 1 + lib/libc/tests/secure/fortify_wchar_test.c | 1 + lib/libc/tests/secure/generate-fortify-tests.lua | 31 ++ sys/sys/select.h | 32 +- 13 files changed, 739 insertions(+), 3 deletions(-) diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile index 7aa9212b97a8..996536beac91 100644 --- a/lib/libc/tests/secure/Makefile +++ b/lib/libc/tests/secure/Makefile @@ -4,6 +4,7 @@ TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} # sys/ headers FORTIFY_TCATS+= random +FORTIFY_TCATS+= select FORTIFY_TCATS+= uio # non-sys/ headers diff --git a/lib/libc/tests/secure/fortify_poll_test.c b/lib/libc/tests/secure/fortify_poll_test.c index 83c0f68b0daa..47648fe54b47 100644 --- a/lib/libc/tests/secure/fortify_poll_test.c +++ b/lib/libc/tests/secure/fortify_poll_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_random_test.c b/lib/libc/tests/secure/fortify_random_test.c index 1eb18cfcaaf4..64c32c6c6a8f 100644 --- a/lib/libc/tests/secure/fortify_random_test.c +++ b/lib/libc/tests/secure/fortify_random_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_select_test.c b/lib/libc/tests/secure/fortify_select_test.c new file mode 100644 index 000000000000..ccd3f97004fc --- /dev/null +++ b/lib/libc/tests/secure/fortify_select_test.c @@ -0,0 +1,669 @@ +/* @generated by `generate-fortify-tests.lua "select"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * 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(FD_SET_before_end); +ATF_TC_BODY(FD_SET_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_SET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_SET_end); +ATF_TC_BODY(FD_SET_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_SET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_SET_after_end); +ATF_TC_BODY(FD_SET_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_SET(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_SET_heap_before_end); +ATF_TC_BODY(FD_SET_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_SET_heap_end); +ATF_TC_BODY(FD_SET_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_SET_heap_after_end); +ATF_TC_BODY(FD_SET_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_SET(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_before_end); +ATF_TC_BODY(FD_CLR_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_CLR(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_end); +ATF_TC_BODY(FD_CLR_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_CLR(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_after_end); +ATF_TC_BODY(FD_CLR_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_CLR(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_heap_before_end); +ATF_TC_BODY(FD_CLR_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_heap_end); +ATF_TC_BODY(FD_CLR_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_CLR_heap_after_end); +ATF_TC_BODY(FD_CLR_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_CLR(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_before_end); +ATF_TC_BODY(FD_ISSET_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + FD_ISSET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_end); +ATF_TC_BODY(FD_ISSET_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + FD_ISSET(__idx, &__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_after_end); +ATF_TC_BODY(FD_ISSET_after_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + fd_set __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + FD_ISSET(__idx, &__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_heap_before_end); +ATF_TC_BODY(FD_ISSET_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_heap_end); +ATF_TC_BODY(FD_ISSET_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(FD_ISSET_heap_after_end); +ATF_TC_BODY(FD_ISSET_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + fd_set * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1); + const size_t __len = FD_SETSIZE + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + FD_ISSET(__idx, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, FD_SET_before_end); + ATF_TP_ADD_TC(tp, FD_SET_end); + ATF_TP_ADD_TC(tp, FD_SET_after_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_before_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_end); + ATF_TP_ADD_TC(tp, FD_SET_heap_after_end); + ATF_TP_ADD_TC(tp, FD_CLR_before_end); + ATF_TP_ADD_TC(tp, FD_CLR_end); + ATF_TP_ADD_TC(tp, FD_CLR_after_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_before_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_end); + ATF_TP_ADD_TC(tp, FD_CLR_heap_after_end); + ATF_TP_ADD_TC(tp, FD_ISSET_before_end); + ATF_TP_ADD_TC(tp, FD_ISSET_end); + ATF_TP_ADD_TC(tp, FD_ISSET_after_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_before_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_end); + ATF_TP_ADD_TC(tp, FD_ISSET_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c index 75f81c0a0750..61ccc8fc5592 100644 --- a/lib/libc/tests/secure/fortify_stdio_test.c +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_stdlib_test.c b/lib/libc/tests/secure/fortify_stdlib_test.c index 8556e1110156..5383b73d4058 100644 --- a/lib/libc/tests/secure/fortify_stdlib_test.c +++ b/lib/libc/tests/secure/fortify_stdlib_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c index 70f247b09e39..918445ca68a1 100644 --- a/lib/libc/tests/secure/fortify_string_test.c +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c index e6a8ea0291de..1cecd7033ae3 100644 --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_uio_test.c b/lib/libc/tests/secure/fortify_uio_test.c index 56d7cf5d9a84..0c709ac8b945 100644 --- a/lib/libc/tests/secure/fortify_uio_test.c +++ b/lib/libc/tests/secure/fortify_uio_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c index 7a91d3b06c75..e2127450f565 100644 --- a/lib/libc/tests/secure/fortify_unistd_test.c +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/fortify_wchar_test.c b/lib/libc/tests/secure/fortify_wchar_test.c index 8c5e0782c65a..31ae02c412a7 100644 --- a/lib/libc/tests/secure/fortify_wchar_test.c +++ b/lib/libc/tests/secure/fortify_wchar_test.c @@ -6,6 +6,7 @@ #include <sys/param.h> #include <sys/random.h> #include <sys/resource.h> +#include <sys/select.h> #include <sys/time.h> #include <sys/uio.h> #include <sys/wait.h> diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua index 23b33acb757b..fdbc6c550551 100755 --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -64,6 +64,7 @@ local includes = { "sys/param.h", "sys/random.h", "sys/resource.h", + "sys/select.h", "sys/time.h", "sys/uio.h", "sys/wait.h", @@ -169,6 +170,36 @@ local all_tests = { exclude = excludes_stack_overflow, }, }, + select = { + -- <sys/select.h> + { + func = "FD_SET", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + { + func = "FD_CLR", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + { + func = "FD_ISSET", + bufsize = "FD_SETSIZE", + buftype = "fd_set", + arguments = { + "__idx", + "__buf", + }, + }, + }, uio = { -- <sys/uio.h> { diff --git a/sys/sys/select.h b/sys/sys/select.h index 1ded44197de9..9b734754b944 100644 --- a/sys/sys/select.h +++ b/sys/sys/select.h @@ -49,6 +49,12 @@ typedef __fd_mask fd_mask; typedef __sigset_t sigset_t; #endif +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include <ssp/ssp.h> +#else +#define __SSP_FORTIFY_LEVEL 0 +#endif + /* * Select uses bit masks of file descriptors in longs. These macros * manipulate such bit fields (the filesystem macros use chars). @@ -75,13 +81,33 @@ typedef struct fd_set { #define fds_bits __fds_bits #endif +#define __fdset_idx_(p, n) ((n) / _NFDBITS) +#if __SSP_FORTIFY_LEVEL == 0 +#define __fdset_idx(p, n) __fdset_idx_(p, n) +#else +__ssp_inline unsigned long +__fdset_idx(fd_set *p, unsigned long idx) +{ + __size_t psz = __ssp_bos0(p); + unsigned long sidx = __fdset_idx_(p, idx); + + if (idx >= FD_SETSIZE) + __chk_fail(); + if (psz / sizeof(__fd_mask) < (sidx + 1)) + __chk_fail(); + + return (sidx); +} +#endif + #define __fdset_mask(n) ((__fd_mask)1 << ((n) % _NFDBITS)) -#define FD_CLR(n, p) ((p)->__fds_bits[(n)/_NFDBITS] &= ~__fdset_mask(n)) +#define FD_CLR(n, p) ((p)->__fds_bits[__fdset_idx(p, n)] &= ~__fdset_mask(n)) #if __BSD_VISIBLE #define FD_COPY(f, t) (void)(*(t) = *(f)) #endif -#define FD_ISSET(n, p) (((p)->__fds_bits[(n)/_NFDBITS] & __fdset_mask(n)) != 0) -#define FD_SET(n, p) ((p)->__fds_bits[(n)/_NFDBITS] |= __fdset_mask(n)) +#define FD_ISSET(n, p) \ + (((p)->__fds_bits[__fdset_idx(p, n)] & __fdset_mask(n)) != 0) +#define FD_SET(n, p) ((p)->__fds_bits[__fdset_idx(p, n)] |= __fdset_mask(n)) #define FD_ZERO(p) do { \ fd_set *_p; \ __size_t _n; \