diff --git a/config.h.in b/config.h.in index 681504ed1..fb64d227b 100644 --- a/config.h.in +++ b/config.h.in @@ -282,6 +282,9 @@ /* Define to 1 if you have the `fexecve' function. */ #undef HAVE_FEXECVE +/* Define to 1 if you have the `fmemopen' function. */ +#undef HAVE_FMEMOPEN + /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH diff --git a/configure b/configure index 478a6bc6f..7820bfc67 100755 --- a/configure +++ b/configure @@ -3220,6 +3220,7 @@ as_fn_append ac_header_c_list " sys/sysmacros.h sys_sysmacros_h HAVE_SYS_SYSMACR as_fn_append ac_header_c_list " sys/syscall.h sys_syscall_h HAVE_SYS_SYSCALL_H" as_fn_append ac_header_c_list " sys/statvfs.h sys_statvfs_h HAVE_SYS_STATVFS_H" as_fn_append ac_func_c_list " fexecve HAVE_FEXECVE" +as_fn_append ac_func_c_list " fmemopen HAVE_FMEMOPEN" as_fn_append ac_func_c_list " killpg HAVE_KILLPG" as_fn_append ac_func_c_list " nl_langinfo HAVE_NL_LANGINFO" as_fn_append ac_func_c_list " faccessat HAVE_FACCESSAT" @@ -20167,6 +20168,7 @@ done + case "$host_os" in hpux*) if test X"$ac_cv_func_pread" = X"yes"; then diff --git a/configure.ac b/configure.ac index 2697c9e35..e589b26db 100644 --- a/configure.ac +++ b/configure.ac @@ -2685,7 +2685,7 @@ dnl dnl Function checks dnl AC_FUNC_GETGROUPS -AC_CHECK_FUNCS_ONCE([fexecve killpg nl_langinfo faccessat wordexp getauxval fseeko]) +AC_CHECK_FUNCS_ONCE([fexecve fmemopen killpg nl_langinfo faccessat wordexp getauxval fseeko]) case "$host_os" in hpux*) if test X"$ac_cv_func_pread" = X"yes"; then diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_json.c b/lib/iolog/regress/fuzz/fuzz_iolog_json.c index 9ab3c0498..a7c397e0c 100644 --- a/lib/iolog/regress/fuzz/fuzz_iolog_json.c +++ b/lib/iolog/regress/fuzz/fuzz_iolog_json.c @@ -34,13 +34,39 @@ #include "iolog_json.h" -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +static FILE * +open_data(const uint8_t *data, size_t size) +{ +#ifdef HAVE_FMEMOPEN + /* Operate in-memory. */ + return fmemopen((void *)data, size, "r"); +#else + char tempfile[] = "/tmp/json.XXXXXX"; + size_t nwritten; + int fd; + + /* Use (unlinked) temporary file. */ + fd = mkstemp(tempfile); + if (fd == -1) + return NULL; + unlink(tempfile); + nwritten = write(fd, data, size); + if (nwritten != size) { + close(fd); + return NULL; + } + lseek(fd, 0, SEEK_SET); + return fdopen(fd, "r"); +#endif +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct eventlog *evlog = NULL; FILE *fp; - /* Operate in-memory. */ - fp = fmemopen((void *)data, size, "r"); + fp = open_data(data, size); if (fp == NULL) return 0; diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c index 17dda622e..c15f84375 100644 --- a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c +++ b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c @@ -32,13 +32,39 @@ #include "sudo_iolog.h" #include "sudo_util.h" -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +static FILE * +open_data(const uint8_t *data, size_t size) +{ +#ifdef HAVE_FMEMOPEN + /* Operate in-memory. */ + return fmemopen((void *)data, size, "r"); +#else + char tempfile[] = "/tmp/legacy.XXXXXX"; + size_t nwritten; + int fd; + + /* Use (unlinked) temporary file. */ + fd = mkstemp(tempfile); + if (fd == -1) + return NULL; + unlink(tempfile); + nwritten = write(fd, data, size); + if (nwritten != size) { + close(fd); + return NULL; + } + lseek(fd, 0, SEEK_SET); + return fdopen(fd, "r"); +#endif +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct eventlog *evlog = NULL; FILE *fp; - /* Operate in-memory. */ - fp = fmemopen((void *)data, size, "r"); + fp = open_data(data, size); if (fp == NULL) return 0; diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_timing.c b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c index 640fa731e..e83726456 100644 --- a/lib/iolog/regress/fuzz/fuzz_iolog_timing.c +++ b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c @@ -40,7 +40,8 @@ #include "sudo_iolog.h" #include "sudo_util.h" -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct iolog_file iolog_file = { true }; struct timing_closure closure; diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers.c b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c index cf7ee4e76..edea66462 100644 --- a/plugins/sudoers/regress/fuzz/fuzz_sudoers.c +++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c @@ -43,7 +43,34 @@ open_sudoers(const char *file, bool doedit, bool *keepopen) return NULL; } -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +static FILE * +open_data(const uint8_t *data, size_t size) +{ +#ifdef HAVE_FMEMOPEN + /* Operate in-memory. */ + return fmemopen((void *)data, size, "r"); +#else + char tempfile[] = "/tmp/sudoers.XXXXXX"; + size_t nwritten; + int fd; + + /* Use (unlinked) temporary file. */ + fd = mkstemp(tempfile); + if (fd == -1) + return NULL; + unlink(tempfile); + nwritten = write(fd, data, size); + if (nwritten != size) { + close(fd); + return NULL; + } + lseek(fd, 0, SEEK_SET); + return fdopen(fd, "r"); +#endif +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FILE *fp; @@ -51,8 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (size < 5) return 0; - /* Operate in-memory. */ - fp = fmemopen((void *)data, size, "r"); + fp = open_data(data, size); if (fp == NULL) return 0; diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c index df98d9982..e1814b1ef 100644 --- a/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c +++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c @@ -38,6 +38,32 @@ open_sudoers(const char *file, bool doedit, bool *keepopen) return fopen(file, "r"); } +static FILE * +open_data(const uint8_t *data, size_t size) +{ +#ifdef HAVE_FMEMOPEN + /* Operate in-memory. */ + return fmemopen((void *)data, size, "r"); +#else + char tempfile[] = "/tmp/ldif.XXXXXX"; + size_t nwritten; + int fd; + + /* Use (unlinked) temporary file. */ + fd = mkstemp(tempfile); + if (fd == -1) + return NULL; + unlink(tempfile); + nwritten = write(fd, data, size); + if (nwritten != size) { + close(fd); + return NULL; + } + lseek(fd, 0, SEEK_SET); + return fdopen(fd, "r"); +#endif +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct sudoers_parse_tree parse_tree; @@ -47,8 +73,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (size < 5) return 0; - /* Operate in-memory. */ - fp = fmemopen((void *)data, size, "r"); + fp = open_data(data, size); if (fp == NULL) return 0;