summaryrefslogtreecommitdiffstats
path: root/lib/iolog/regress/fuzz
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_json.c123
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_json.dict21
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_legacy.c119
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict42
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_timing.c132
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_timing.dict89
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"