diff options
Diffstat (limited to '')
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_json.c | 123 | ||||
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_json.dict | 21 | ||||
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_legacy.c | 119 | ||||
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict | 42 | ||||
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_timing.c | 132 | ||||
-rw-r--r-- | lib/iolog/regress/fuzz/fuzz_iolog_timing.dict | 89 |
6 files changed, 526 insertions, 0 deletions
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_json.c b/lib/iolog/regress/fuzz/fuzz_iolog_json.c new file mode 100644 index 0000000..80f6c9f --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_json.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#if defined(HAVE_STDINT_H) +# include <stdint.h> +#elif defined(HAVE_INTTYPES_H) +# include <inttypes.h> +#endif + +#include "sudo_compat.h" +#include "sudo_debug.h" +#include "sudo_eventlog.h" +#include "sudo_fatal.h" +#include "sudo_iolog.h" +#include "sudo_plugin.h" +#include "sudo_util.h" + +#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 +} + +static int +fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[], struct sudo_conv_callback *callback) +{ + int n; + + for (n = 0; n < num_msgs; n++) { + const struct sudo_conv_message *msg = &msgs[n]; + + switch (msg->msg_type & 0xff) { + case SUDO_CONV_PROMPT_ECHO_ON: + case SUDO_CONV_PROMPT_MASK: + case SUDO_CONV_PROMPT_ECHO_OFF: + /* input not supported */ + return -1; + case SUDO_CONV_ERROR_MSG: + case SUDO_CONV_INFO_MSG: + /* no output for fuzzers */ + break; + default: + return -1; + } + } + return 0; +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct eventlog *evlog = NULL; + FILE *fp; + + initprogname("fuzz_iolog_json"); + if (getenv("SUDO_FUZZ_VERBOSE") == NULL) + sudo_warn_set_conversation(fuzz_conversation); + + fp = open_data(data, size); + if (fp == NULL) + return 0; + + /* Parsed contents of an log.json file are stored in evlog. */ + evlog = calloc(1, sizeof(*evlog)); + if (evlog != NULL) { + evlog->runuid = (uid_t)-1; + evlog->rungid = (gid_t)-1; + evlog->exit_value = -1; + + /* Try to parse buffer as a JSON-format I/O log info file. */ + iolog_parse_loginfo_json(fp, "fuzz.json", evlog); + eventlog_free(evlog); + } + fclose(fp); + + fflush(stdout); + + return 0; +} diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_json.dict b/lib/iolog/regress/fuzz/fuzz_iolog_json.dict new file mode 100644 index 0000000..2caf63d --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_json.dict @@ -0,0 +1,21 @@ +# I/O log JSON keywords +"\"columns\"" +"\"command\"" +"\"dumped_core\"" +"\"exit_value\"" +"\"lines\"" +"\"run_time\"" +"\"runargv\"" +"\"runenv\"" +"\"rungid\"" +"\"rungroup\"" +"\"runuid\"" +"\"runuser\"" +"\"runchroot\"" +"\"runcwd\"" +"\"signal\"" +"\"submitcwd\"" +"\"submithost\"" +"\"submituser\"" +"\"timestamp\"" +"\"ttyname\""" diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c new file mode 100644 index 0000000..207374c --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#if defined(HAVE_STDINT_H) +# include <stdint.h> +#elif defined(HAVE_INTTYPES_H) +# include <inttypes.h> +#endif + +#include "sudo_compat.h" +#include "sudo_debug.h" +#include "sudo_eventlog.h" +#include "sudo_fatal.h" +#include "sudo_iolog.h" +#include "sudo_plugin.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 +} + +static int +fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[], struct sudo_conv_callback *callback) +{ + int n; + + for (n = 0; n < num_msgs; n++) { + const struct sudo_conv_message *msg = &msgs[n]; + + switch (msg->msg_type & 0xff) { + case SUDO_CONV_PROMPT_ECHO_ON: + case SUDO_CONV_PROMPT_MASK: + case SUDO_CONV_PROMPT_ECHO_OFF: + /* input not supported */ + return -1; + case SUDO_CONV_ERROR_MSG: + case SUDO_CONV_INFO_MSG: + /* no output for fuzzers */ + break; + default: + return -1; + } + } + return 0; +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct eventlog *evlog = NULL; + FILE *fp; + + initprogname("fuzz_iolog_legacy"); + if (getenv("SUDO_FUZZ_VERBOSE") == NULL) + sudo_warn_set_conversation(fuzz_conversation); + + fp = open_data(data, size); + if (fp == NULL) + return 0; + + /* Parsed contents of an I/O log info file are stored in evlog. */ + evlog = calloc(1, sizeof(*evlog)); + if (evlog != NULL) { + evlog->runuid = (uid_t)-1; + evlog->rungid = (gid_t)-1; + + /* Try to parse buffer as a legacy-format I/O log info file. */ + iolog_parse_loginfo_legacy(fp, "fuzz.legacy", evlog); + eventlog_free(evlog); + } + fclose(fp); + fflush(stdout); + + return 0; +} diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict new file mode 100644 index 0000000..d524d49 --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict @@ -0,0 +1,42 @@ +# Legacy I/O log info file: +# timestamp:submit_user:run_user:run_group:tty:lines:columns +# working directory +# command [args] + +# users and groups +"millert" +"root" +"bin" +"wheel" +"operator" +"testuser" +"alice" +"bob" +"users" + +# terminals +"/dev/console" +"/dev/tty00" +"/dev/tty01" +"/dev/pts/0" +"/dev/pts/1" +"/dev/ttyp2" +"/dev/ttyp3" + +# directories +"/root" +"/home/millert" +"/home/alice" +"/home/bob" +"/tmp" +"/usr/local" +"/usr/src" + +# commands +"/bin/ls" +"/usr/bin/id -u" +"/usr/bin/su -" +"/usr/bin/mailq" +"/usr/bin/make -C /usr/src/usr.bin/sort install" +"/usr/bin/apt update" +"/usr/bin/rpm -e sudo" diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_timing.c b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c new file mode 100644 index 0000000..dac9736 --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> + +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#if defined(HAVE_STDINT_H) +# include <stdint.h> +#elif defined(HAVE_INTTYPES_H) +# include <inttypes.h> +#endif +#ifdef HAVE_STDBOOL_H +# include <stdbool.h> +#else +# include "compat/stdbool.h" +#endif /* HAVE_STDBOOL_H */ + +#include "sudo_compat.h" +#include "sudo_debug.h" +#include "sudo_eventlog.h" +#include "sudo_fatal.h" +#include "sudo_iolog.h" +#include "sudo_plugin.h" +#include "sudo_util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +static int +fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[], struct sudo_conv_callback *callback) +{ + int n; + + for (n = 0; n < num_msgs; n++) { + const struct sudo_conv_message *msg = &msgs[n]; + + switch (msg->msg_type & 0xff) { + case SUDO_CONV_PROMPT_ECHO_ON: + case SUDO_CONV_PROMPT_MASK: + case SUDO_CONV_PROMPT_ECHO_OFF: + /* input not supported */ + return -1; + case SUDO_CONV_ERROR_MSG: + case SUDO_CONV_INFO_MSG: + /* no output for fuzzers */ + break; + default: + return -1; + } + } + return 0; +} + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct iolog_file iolog_file = { true }; + struct timing_closure closure; + char logdir[] = "/tmp/timing.XXXXXX"; + int dfd = -1, fd = -1; + + initprogname("fuzz_iolog_timing"); + if (getenv("SUDO_FUZZ_VERBOSE") == NULL) + sudo_warn_set_conversation(fuzz_conversation); + + /* I/O logs consist of multiple files in a directory. */ + if (mkdtemp(logdir) == NULL) + return 0; + + /* Create a timing file from the supplied data. */ + dfd = open(logdir, O_RDONLY); + if (dfd == -1) + goto cleanup; + + fd = openat(dfd, "timing", O_WRONLY|O_CREAT|O_EXCL, S_IRWXU); + if (fd == -1) + goto cleanup; + + if (write(fd, data, size) != (ssize_t)size) + goto cleanup; + close(fd); + fd = -1; + + /* Open the timing file we wrote and try to parse it. */ + if (!iolog_open(&iolog_file, dfd, IOFD_TIMING, "r")) + goto cleanup; + + memset(&closure, 0, sizeof(closure)); + closure.decimal = "."; + for (;;) { + if (iolog_read_timing_record(&iolog_file, &closure) != 0) + break; + } + iolog_close(&iolog_file, NULL); + +cleanup: + if (dfd != -1) { + if (fd != -1) + close(fd); + unlinkat(dfd, "timing", 0); + close(dfd); + } + rmdir(logdir); + fflush(stdout); + + return 0; +} + +/* STUB */ +bool +iolog_swapids(bool restore) +{ + return false; +} diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict b/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict new file mode 100644 index 0000000..42bdeb5 --- /dev/null +++ b/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict @@ -0,0 +1,89 @@ +# I/O log timing lines are formatted as: +# [0-4] sleep_time num_bytes +# 5 sleep_time lines cols +# 7 sleep_time signum|sigabbrev + +# Signal abbreviations +"ABRT" +"ALRM" +"BUS" +"CANCEL" +"CHLD" +"CLD" +"CONT" +"CONT" +"EMT" +"FPE" +"FREEZE" +"HUP" +"ILL" +"INFO" +"INT" +"IO" +"IOT" +"KILL" +"LOST" +"LWP" +"PIPE" +"POLL" +"PROF" +"PWR" +"QUIT" +"SEGV" +"STKFLT" +"STOP" +"STOP" +"SYS" +"TERM" +"THAW" +"TRAP" +"TSTP" +"TSTP" +"TTIN" +"TTIN" +"TTOU" +"TTOU" +"UNUSED" +"URG" +"USR1" +"USR2" +"VTALRM" +"WAITING" +"WINCH" +"XCPU" +"XFSZ" + +# Signal numbers, 0-32 +"0" +"1" +"2" +"3" +"4" +"5" +"6" +"7" +"8" +"9" +"10" +"11" +"12" +"13" +"14" +"15" +"16" +"17" +"18" +"19" +"20" +"21" +"22" +"23" +"24" +"25" +"26" +"27" +"28" +"29" +"30" +"31" +"32" |