From 28297b1e84ad330c115c0dc56055ee560b2ba974 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 11 Apr 2021 05:17:03 +0200 Subject: [PATCH] tests: fuzzing target for zlog_5424 code This just tries logging messages in random ways to allow the fuzzer to do its thing and try to find weird edge cases. Signed-off-by: David Lamparter --- tests/.gitignore | 1 + tests/lib/fuzz_zlog.c | 130 ++++++++++++++++++++++++++++++++++ tests/lib/fuzz_zlog_inputs.py | 41 +++++++++++ tests/lib/subdir.am | 8 +++ 4 files changed, 180 insertions(+) create mode 100644 tests/lib/fuzz_zlog.c create mode 100644 tests/lib/fuzz_zlog_inputs.py diff --git a/tests/.gitignore b/tests/.gitignore index 53dbd68c9a..70d0ef6e0a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -21,6 +21,7 @@ /lib/cli/test_commands_defun.c /lib/northbound/test_oper_data /lib/cxxcompat +/lib/fuzz_zlog /lib/test_assert /lib/test_atomlist /lib/test_buffer diff --git a/tests/lib/fuzz_zlog.c b/tests/lib/fuzz_zlog.c new file mode 100644 index 0000000000..14c857118b --- /dev/null +++ b/tests/lib/fuzz_zlog.c @@ -0,0 +1,130 @@ +/* + * zlog fuzzer target. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "log.h" +#include "zlog_5424.h" +#include "command.h" + +struct input_opts { + uint16_t out1_debug; + uint16_t out2_debug; + uint16_t out3_warn; + uint8_t fmt; + uint8_t dst; +}; + +static char buffer[65536]; + +int main(int argc, char **argv) +{ + struct input_opts io; + int fd; + int pair[2] = {-1, -1}; + + if (read(0, &io, sizeof(io)) != sizeof(io)) + return 1; + if (io.fmt > ZLOG_FMT_LAST) + return 1; + + switch (io.dst) { + case 0: + fd = 1; + break; + case 1: + socketpair(AF_UNIX, SOCK_STREAM, 0, pair); + fd = pair[0]; + break; + case 2: + socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair); + fd = pair[0]; + break; + case 3: + socketpair(AF_UNIX, SOCK_DGRAM, 0, pair); + fd = pair[0]; + break; + default: + return 1; + } + + pid_t child = -1; + + if (pair[1] != -1) { + child = fork(); + + if (child == 0) { + char buf[4096]; + + close(pair[0]); + + while (read(pair[1], buf, sizeof(buf)) > 0) + ; + exit(0); + } else if (child == -1) { + perror("fork"); + return 1; + } + close(pair[1]); + } + + for (size_t i = 0; i < sizeof(buffer); i++) + buffer[i] = (i | 0x20) & 0x7f; + + zlog_aux_init("FUZZBALL: ", LOG_DEBUG); + zlog_tls_buffer_init(); + + struct zlog_cfg_5424 cfg[1] = {}; + + zlog_5424_init(cfg); + + cfg->facility = LOG_DAEMON; + cfg->prio_min = LOG_DEBUG; + cfg->kw_version = true; + cfg->kw_location = true; + cfg->kw_uid = true; + cfg->kw_ec = true; + cfg->kw_args = true; + + cfg->ts_flags = 9; + cfg->fmt = io.fmt; + cfg->dst = ZLOG_5424_DST_FD; + cfg->fd = fd; + + cmd_hostname_set("TEST"); + cfg->master = thread_master_create("TEST"); + + zlog_5424_apply_dst(cfg); + + zlog_debug("test #1 %.*s", (int)io.out1_debug, buffer); + zlog_debug("test #2 %.*s", (int)io.out2_debug, buffer); + zlog_warn("test #1 %.*s", (int)io.out3_warn, buffer); + + zlog_tls_buffer_flush(); + zlog_tls_buffer_fini(); + + /* AFL++ seems to do some weird stuff with its fuzzing target, make + * sure the fork() child is zapped here rather than creating hordes + * of it. + */ + close(fd); + if (child != -1) + kill(child, SIGTERM); + + return 0; +} diff --git a/tests/lib/fuzz_zlog_inputs.py b/tests/lib/fuzz_zlog_inputs.py new file mode 100644 index 0000000000..74f3286c5f --- /dev/null +++ b/tests/lib/fuzz_zlog_inputs.py @@ -0,0 +1,41 @@ +# zlog fuzz-tester input generator +# +# Copyright (C) 2021 David Lamparter for NetDEF, Inc. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; see the file COPYING; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +from itertools import chain +import struct + +lengths = set([128]) +# lengths = [[i, i + 1, i + 3, i - 1, i - 3] for i in lengths] +# lengths = set([i for i in chain(*lengths) if i >= 0]) + +dsts = [0, 1, 2, 3] +fmts = [0, 1, 2, 3] + + +def combo(): + for l0 in lengths: + for l1 in lengths: + for l2 in lengths: + for fmt in fmts: + for dst in dsts: + yield (l0, l1, l2, fmt, dst) + + +for i, tup in enumerate(combo()): + with open("input/i%d" % i, "wb") as fd: + fd.write(struct.pack("HHHBB", *tup)) diff --git a/tests/lib/subdir.am b/tests/lib/subdir.am index 00fe93278b..6c897b132e 100644 --- a/tests/lib/subdir.am +++ b/tests/lib/subdir.am @@ -65,6 +65,14 @@ tests_lib_cxxcompat_SOURCES = tests/lib/cxxcompat.c tests_lib_cxxcompat_LDADD = $(ALL_TESTS_LDADD) +check_PROGRAMS += tests/lib/fuzz_zlog +tests_lib_fuzz_zlog_CFLAGS = $(TESTS_CFLAGS) +tests_lib_fuzz_zlog_CPPFLAGS = $(TESTS_CPPFLAGS) +tests_lib_fuzz_zlog_LDADD = $(ALL_TESTS_LDADD) +tests_lib_fuzz_zlog_SOURCES = tests/lib/fuzz_zlog.c +EXTRA_DIST += tests/lib/fuzz_zlog_inputs.py + + check_PROGRAMS += tests/lib/cli/test_cli tests_lib_cli_test_cli_CFLAGS = $(TESTS_CFLAGS) tests_lib_cli_test_cli_CPPFLAGS = $(TESTS_CPPFLAGS) -- 2.39.5