Commit 1c18debe authored by Daniel Salzman's avatar Daniel Salzman

tests-fuzz: add new stdio-wrapped knotd

parent 6144cc40
......@@ -457,11 +457,11 @@ src/zscanner/tests/tests.h
src/zscanner/tests/zscanner-tool.c
tests-fuzz/fuzz_packet.c
tests-fuzz/fuzz_zscanner.c
tests-fuzz/knotd_wrap/afl-loop.h
tests-fuzz/knotd_wrap/server.c
tests-fuzz/knotd_wrap/tcp-handler.c
tests-fuzz/knotd_wrap/udp-handler.c
tests-fuzz/main.c
tests-fuzz/wrap/afl-loop.h
tests-fuzz/wrap/server.c
tests-fuzz/wrap/tcp-handler.c
tests-fuzz/wrap/udp-handler.c
tests/contrib/test_base32hex.c
tests/contrib/test_base64.c
tests/contrib/test_dynarray.c
......
......@@ -2,7 +2,7 @@
/Makefile
/knotd_stdio
/wrap/main.c
/knotd_wrap/main.c
*.trs
*.log
......
......@@ -11,7 +11,30 @@ FUZZERS = \
fuzz_packet \
fuzz_zscanner
check_PROGRAMS = $(FUZZERS)
check_PROGRAMS = \
$(FUZZERS) \
knotd_stdio
# knotd_stdio (AFL)
nodist_knotd_stdio_SOURCES = knotd_wrap/main.c
knotd_stdio_SOURCES = \
knotd_wrap/server.c \
knotd_wrap/tcp-handler.c \
knotd_wrap/udp-handler.c
knotd_stdio_CPPFLAGS = $(AM_CPPFLAGS) $(liburcu_CFLAGS)
knotd_stdio_LDADD = $(top_builddir)/src/libknotd.la $(top_builddir)/src/libcontrib.la \
$(liburcu_LIBS)
BUILT_SOURCES = knotd_wrap/main.c
CLEANFILES = knotd_wrap/main.c
knotd_wrap/main.c: $(top_builddir)/src/utils/knotd/main.c
@echo '#include "afl-loop.h"' > $@
@$(SED) -e 's/for (;;)/while (__AFL_LOOP(10000))/' $(top_srcdir)/src/utils/knotd/main.c >> $@
# Simple function wrappers (AFL, libFuzzer, tests)
fuzz_packet_SOURCES = fuzz_packet.c
fuzz_packet_CPPFLAGS = $(AM_CPPFLAGS)
......
https://gitlab.labs.nic.cz/knot/knot-dns/wikis/Fuzzing
# Fuzzing stdio-wrapped knotd with [AFL](http://lcamtuf.coredump.cx/afl/)
1. Ensure [Clang](https://clang.llvm.org)
1. Ensure AFL 1.83b+ or install fresh one
2. `curl -O -L http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz`
2. `tar -xzf afl-latest.tgz`
2. `cd afl-*/`
2. `make`
2. `make -C llvm_mode`
2. `sudo make install`
1. Compile Knot DNS with `afl-clang` compiler
2. `CC=afl-clang-fast ./configure --disable-shared --disable-utilities --disable-documentation`
2. `make`
1. Try running `knotd_stdio`
2. `cd tests-fuzz`
2. `make check-compile`
2. `mkdir -p /tmp/knotd-fuzz/rundir /tmp/knotd-fuzz/storage`
2. `./knotd_stdio -c ./knotd_wrap/knot_stdio.conf`
2. (Consider adding zones or modules to the configuration)
1. Prepare an initial corpus
2. Checkout the dns-fuzzing repository `git clone https://github.com/CZ-NIC/dns-fuzzing in`
2. (Add more custom test cases to `in/packet/`)
1. Minimize the tested corpus with `afl-cmin` and simple packet parser
2. `afl-cmin -i in/packet/ -o min -- ./fuzz_packet`
1. Run the fuzzer
2. `AFL_PERSISTENT=1 afl-fuzz -m 1000M -i min -o out -- ./knotd_stdio -c knotd_wrap/knot_stdio.conf`
2. (Consider parallel fuzzing, see `afl-fuzz -h`)
NOTE: Sanitizer utilization is a bit problematical with AFL, see [notes_for_asan.txt]
(https://github.com/mirrorer/afl/blob/master/docs/notes_for_asan.txt).
# Fuzzing with [libFuzzer](https://llvm.org/docs/LibFuzzer.html) (requires Clang 6.0+)
1. Ensure [Clang](https://clang.llvm.org) with `-fsanitize=fuzzer` support (e.g. [LLVM](https://apt.llvm.org))
1. Configure with
2. `./configure --with-fuzzer --disable-shared --disable-daemon --disable-utilities
--disable-documentation --disable-modules`
2. (You should also add `--with-sanitizer=`
`address` for [ASAN](http://clang.llvm.org/docs/AddressSanitizer.html) or
`undefined` for [UBSAN](http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html))
2. (Add proper `CC=clang-6.0` if necessary)
1. Compile Knot DNS:
2. `make`
1. Create and check the fuzzing binaries
2. `cd tests-fuzz`
2. `make check`
1. Download the corpora
2. `git submodule init`
2. `git submodule update --recursive --remote`
1. (Optional) add more test cases
2. `./fuzz_packet -merge=1 fuzz_packet.in <DIR_WITH_NEW_PACKET_TEST_CASES>`
2. `./fuzz_zscanner -merge=1 fuzz_zscanner.in <DIR_WITH_NEW_ZSCANNER_TEST_CASES>`
1. Run the fuzzer
2. (Set proper symbolizer if necessary
`export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-6.0` for ASAN or
`export UBSAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-6.0` for UBSAN)
2. `./fuzz_packet fuzz_packet.in` or `./fuzz_zscanner fuzz_zscanner.in`
2. (Add parallel fuzzing `-jobs=<CPUS>`
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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 3 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. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __AFL_LOOP
#define __AFL_LOOP(x) (0)
#endif
server:
udp-workers: 1
tcp-workers: 1
background-workers: 1
rundir: /tmp/knotd-fuzz/rundir
log:
- target: stderr
any: info
template:
- id: default
storage: /tmp/knotd-fuzz/storage
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -12,12 +12,9 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Wrap function server_reconfigure to initialize udp_master to stdin
*/
#define server_reconfigure _orig_server_reconfigure
#define server_reconfigure orig_server_reconfigure
#include "knot/server/server.c"
#undef server_reconfigure
......@@ -25,7 +22,6 @@ extern void udp_master_init_stdio(server_t *server);
void server_reconfigure(conf_t *conf, server_t *server)
{
log_info("AFL, Wrap server_reconfigure()");
_orig_server_reconfigure(conf, server);
orig_server_reconfigure(conf, server);
udp_master_init_stdio(server);
}
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -14,12 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define tcp_master _orig_tcp_master
#define tcp_master orig_tcp_master
#include "knot/server/tcp-handler.c"
#undef tcp_master
int tcp_master(dthread_t *thread)
{
log_info("AFL, tcp_master out of order");
log_info("AFL, empty TCP handler");
return 0;
}
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -12,26 +12,19 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Udp handler listen on stdin and send to stdout.
* To use this handler initialize it with udp_master_init_stdin.
*/
#include <stdbool.h>
#include "knot/server/udp-handler.c"
#include "knot/common/log.h"
struct udp_stdin {
typedef struct {
struct iovec iov[NBUFS];
uint8_t buf[NBUFS][KNOT_WIRE_MAX_PKTSIZE];
struct sockaddr_storage addr;
bool afl_persistent;
};
} udp_stdin_t;
static inline void next(struct udp_stdin *rq)
static inline void next(udp_stdin_t *rq)
{
if (rq->afl_persistent) {
raise(SIGSTOP);
......@@ -42,8 +35,11 @@ static inline void next(struct udp_stdin *rq)
static void *udp_stdin_init(void)
{
struct udp_stdin *rq = malloc(sizeof(struct udp_stdin));
memset(rq, 0, sizeof(struct udp_stdin));
udp_stdin_t *rq = calloc(1, sizeof(udp_stdin_t));
if (rq == NULL) {
return NULL;
}
for (unsigned i = 0; i < NBUFS; ++i) {
rq->iov[i].iov_base = rq->buf[i];
rq->iov[i].iov_len = KNOT_WIRE_MAX_PKTSIZE;
......@@ -55,21 +51,20 @@ static void *udp_stdin_init(void)
a->sin_port = 42;
rq->afl_persistent = getenv("AFL_PERSISTENT") != NULL;
return rq;
}
static int udp_stdin_deinit(void *d)
static void udp_stdin_deinit(void *d)
{
free(d);
return 0;
}
static int udp_stdin_recv(int fd, void *d)
{
struct udp_stdin *rq = (struct udp_stdin *)d;
rq->iov[RX].iov_len = fread(rq->iov[RX].iov_base,
1, KNOT_WIRE_MAX_PKTSIZE, stdin);
udp_stdin_t *rq = (udp_stdin_t *)d;
rq->iov[RX].iov_len = fread(rq->iov[RX].iov_base, 1,
KNOT_WIRE_MAX_PKTSIZE, stdin);
if (rq->iov[RX].iov_len == 0) {
next(rq);
}
......@@ -79,29 +74,26 @@ static int udp_stdin_recv(int fd, void *d)
static int udp_stdin_handle(udp_context_t *ctx, void *d)
{
struct udp_stdin *rq = (struct udp_stdin *)d;
udp_stdin_t *rq = (udp_stdin_t *)d;
udp_handle(ctx, STDIN_FILENO, &rq->addr, &rq->iov[RX], &rq->iov[TX]);
return 0;
}
static int udp_stdin_send(void *d)
{
struct udp_stdin *rq = (struct udp_stdin *)d;
udp_stdin_t *rq = (udp_stdin_t *)d;
next(rq);
return 0;
}
/*!
* \brief Initialize udp_handler with stdio
*/
void udp_master_init_stdio(server_t *server) {
log_info("AFL, UDP handler listen on stdin");
log_info("AFL, UDP handler listening on stdin");
// register our dummy interface to server
iface_t *ifc = calloc(1, sizeof(iface_t));
// Register dummy interface to server.
iface_t *ifc = calloc(1, sizeof(*ifc));
assert(ifc);
ifc->fd_udp = calloc(1, sizeof(int));
ifc->fd_udp = calloc(1, sizeof(*ifc->fd_udp));
assert(ifc->fd_udp);
ifc->fd_udp[0] = STDIN_FILENO;
ifc->fd_udp_count = 1;
......
#pragma once
#ifndef __AFL_COMPILER
#define __AFL_LOOP(x) (0)
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment