diff -Nur ORIG.bind-9.13.2/bin/named/fuzz.c bind-9.13.2/bin/named/fuzz.c --- ORIG.bind-9.13.2/bin/named/fuzz.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/bin/named/fuzz.c 2018-08-04 03:54:45.754294759 +0200 @@ -33,10 +33,6 @@ #include #include -#ifndef __AFL_LOOP -#error To use American Fuzzy Lop you have to set CC to afl-clang-fast!!! -#endif - /* * We are using pthreads directly because we might be using it with * unthreaded version of BIND, where all thread functions are @@ -589,7 +585,6 @@ * this signature ("##SIG_AFL_PERSISTENT##") and runs the binary * in persistent mode if it's present. */ - __AFL_LOOP(0); return (NULL); } @@ -739,7 +734,9 @@ return; } +#if 0 raise(SIGSTOP); +#endif RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); @@ -752,8 +749,7 @@ void named_fuzz_setup(void) { -#ifdef ENABLE_AFL - if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) { +#if 0 pthread_t thread; void *(fn) = NULL; @@ -779,6 +775,5 @@ RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0); RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0); RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0); - } #endif /* ENABLE_AFL */ } diff -Nur ORIG.bind-9.13.2/bin/named/main.c bind-9.13.2/bin/named/main.c --- ORIG.bind-9.13.2/bin/named/main.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/bin/named/main.c 2018-08-04 03:57:28.339549734 +0200 @@ -1318,13 +1318,262 @@ } #endif /* HAVE_LIBSCF */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void enter_namespaces(void) { + if (linuxEnterNs(CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWIPC) == false) { + exit(1); + } + if (linuxIfaceUp("lo") == false) { + exit(1); + } + if (linuxMountTmpfs("/tmp") == false) { + exit(1); + } +} + +static size_t rlen = 0; +static const uint8_t *rbuf = NULL; + +__attribute__((no_sanitize("memory"))) __attribute__((no_sanitize("address"))) static void * +bind_thr(void *unused __attribute__((unused))) { + while (!named_g_run_done) { + usleep(10000); + } + + int myfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (myfd == -1) { + perror("socket"); + exit(1); + } + int val = 1; + if (setsockopt(myfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) { + perror("setsockopt(SO_REUSEADDR)"); + } + + const struct sockaddr_in saddr = { + .sin_family = AF_INET, + .sin_port = htons(53), + .sin_addr.s_addr = inet_addr("127.0.0.2"), + }; + if (bind(myfd, &saddr, sizeof(saddr)) == -1) { + perror("bind"); + exit(1); + } + + if (listen(myfd, SOMAXCONN) == -1) { + perror("listen"); + exit(1); + } + + for (;;) { + struct sockaddr_in cli; + socklen_t cli_len = sizeof(cli); + + int nfd = accept(myfd, &cli, &cli_len); + if (nfd == -1) { + perror("accept"); + exit(1); + } + + static char b[1024 * 1024]; + ssize_t sz = recv(nfd, b, sizeof(b), 0); + if (sz <= 0) { + perror("recv"); + _exit(1); + } + if (sz < 4) { + close(nfd); + continue; + } + + /* It's a response, so set QR bit to 1 */ + uint8_t qr = rbuf[0] | 0x80; + + uint16_t t_l = htons(rlen + 2); + const struct iovec iov[] = { + { + .iov_base = &t_l, + .iov_len = sizeof(t_l), + }, + { + .iov_base = &b[2], + .iov_len = 2, + }, + { + .iov_base = &qr, + .iov_len = 1, + }, + { + .iov_base = (void *)&rbuf[1], + .iov_len = rlen - 1, + }, + }; + + if (writev(nfd, iov, 4) == -1) { + perror("writev() failed"); + } + + close(nfd); + } + + return NULL; +} + +static void rndloop(int sock) { + const struct sockaddr_in bsaddr = { + .sin_family = AF_INET, + .sin_port = htons(0), + .sin_addr.s_addr = htonl((((uint32_t)util_rnd64()) & 0x00FFFFFF) | 0x7F000000), + }; + if (bind(sock, (const struct sockaddr *)&bsaddr, sizeof(bsaddr)) == -1) { + perror("bind"); + } +} + +__attribute__((no_sanitize("memory"))) __attribute__((no_sanitize("address"))) static void * +connect_thr(void *unused __attribute__((unused))) { + while (!named_g_run_done) { + usleep(10000); + } + usleep(100000); + + for (;;) { + int myfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (myfd == -1) { + perror("socket"); + exit(1); + } + int val = 1; + if (setsockopt(myfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) { + perror("setsockopt(SO_REUSEADDR)"); + } + + rndloop(myfd); + + const struct sockaddr_in saddr = { + .sin_family = AF_INET, + .sin_port = htons(53), + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + if (connect(myfd, &saddr, sizeof(saddr)) == -1) { + close(myfd); + continue; + } + + const uint8_t *buf; + size_t len; + HF_ITER(&buf, &len); + + rlen = 0; + rbuf = NULL; + + if (len < 32) { + close(myfd); + continue; + } + + uint32_t tmplen = *((const uint32_t *)buf); + + buf = &buf[sizeof(uint32_t)]; + len -= sizeof(uint32_t); + + tmplen %= len; + + rbuf = &buf[tmplen]; + rlen = len - tmplen; + len = tmplen; + + uint16_t t_l = htons(len); + const struct iovec iov[] = { + { + .iov_base = &t_l, + .iov_len = sizeof(t_l), + }, + { + .iov_base = (void *)buf, + .iov_len = len, + }, + }; + + if (writev(myfd, iov, 2) == -1) { + perror("write"); + close(myfd); + continue; + } + + if (shutdown(myfd, SHUT_WR) == -1) { + if (errno == ENOTCONN) { + close(myfd); + continue; + } + perror("shutdown"); + _exit(1); + } + + uint8_t b[1024 * 512]; + while (recv(myfd, b, sizeof(b), 0) > 0) + ; + close(myfd); + } +} + +static void launch_thr(void) { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 1024 * 1024 * 4); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_t t; + if (pthread_create(&t, &attr, bind_thr, NULL) < 0) { + perror("pthread_create(bind_thr)"); + exit(1); + } + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 1024 * 1024 * 4); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (pthread_create(&t, &attr, connect_thr, NULL) < 0) { + perror("pthread_create(connect_thr)"); + exit(1); + } +} + /* main entry point, possibly hooked */ -int -main(int argc, char *argv[]) { - isc_result_t result; +int main(int argc, char *argv[]) { + if (!getenv("NO_FUZZ")) { + named_g_fuzz_addr = "127.0.0.1:53"; + named_g_fuzz_type = isc_fuzz_client; + enter_namespaces(); + launch_thr(); + } + + isc_result_t result; #ifdef HAVE_LIBSCF - char *instance = NULL; + char *instance = NULL; #endif #ifdef HAVE_GPERFTOOLS_PROFILER @@ -1373,17 +1622,17 @@ parse_command_line(argc, argv); -#ifdef ENABLE_AFL +#if 0 if (named_g_fuzz_type != isc_fuzz_none) { named_fuzz_setup(); } +#endif if (named_g_fuzz_type == isc_fuzz_resolver) { dns_resolver_setfuzzing(); } else if (named_g_fuzz_type == isc_fuzz_http) { isc_httpd_setfinishhook(named_fuzz_notify); } -#endif /* * Warn about common configuration error. */ diff -Nur ORIG.bind-9.13.2/bin/named/server.c bind-9.13.2/bin/named/server.c --- ORIG.bind-9.13.2/bin/named/server.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/bin/named/server.c 2018-08-04 03:54:45.762294623 +0200 @@ -9202,7 +9202,7 @@ "loading configuration"); CHECKFATAL(load_zones(server, ISC_TRUE, ISC_FALSE), "loading zones"); -#ifdef ENABLE_AFL +#if 1 named_g_run_done = ISC_TRUE; #endif } diff -Nur ORIG.bind-9.13.2/compile.sh bind-9.13.2/compile.sh --- ORIG.bind-9.13.2/compile.sh 1970-01-01 01:00:00.000000000 +0100 +++ bind-9.13.2/compile.sh 2018-08-04 03:59:40.557326027 +0200 @@ -0,0 +1,25 @@ +#!/bin/sh + +set -ex + +export CC=/home/jagger/src/honggfuzz/hfuzz_cc/hfuzz-clang +export CXX=/home/jagger/src/honggfuzz/hfuzz_cc/hfuzz-clang++ +export CFLAGS="-fsanitize=address -Wno-shift-negative-value -Wno-logical-not-parentheses -g -ggdb -O0" +./configure \ + --prefix=/home/jagger/fuzz/bind/dist/ \ + --enable-threads \ + --without-gssapi \ + --disable-chroot \ + --disable-linux-caps \ + --enable-seccomp \ + --without-libtool \ + --enable-ipv6 \ + --enable-atomic \ + --enable-epoll \ + --enable-afl \ + --disable-crypto-rand \ + --disable-backtrace \ + --with-openssl=yes + +make clean +make -j$(nproc) diff -Nur ORIG.bind-9.13.2/lib/dns/request.c bind-9.13.2/lib/dns/request.c --- ORIG.bind-9.13.2/lib/dns/request.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/lib/dns/request.c 2018-08-04 03:54:45.762294623 +0200 @@ -770,6 +770,7 @@ if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) tcp = ISC_TRUE; + tcp = ISC_TRUE; share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0); again: @@ -1050,6 +1051,8 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, isc_mem_t *mctx) { + options |= DNS_REQUESTOPT_TCP; + isc_buffer_t *buf1 = NULL; isc_buffer_t *buf2 = NULL; isc_result_t result; @@ -1106,9 +1109,10 @@ * Copy rendered message to exact sized buffer. */ isc_buffer_usedregion(buf1, &r); + options |= DNS_REQUESTOPT_TCP; if ((options & DNS_REQUESTOPT_TCP) != 0) { tcp = ISC_TRUE; - } else if (r.length > 512) { + } else if (r.length >= 512) { result = DNS_R_USETCP; goto cleanup; } diff -Nur ORIG.bind-9.13.2/lib/dns/resolver.c bind-9.13.2/lib/dns/resolver.c --- ORIG.bind-9.13.2/lib/dns/resolver.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/lib/dns/resolver.c 2018-08-04 03:54:45.766294556 +0200 @@ -1911,6 +1911,7 @@ } query->mctx = fctx->mctx; query->options = options; + query->options = options | DNS_FETCHOPT_TCP; query->attributes = 0; query->sends = 0; query->connects = 0; diff -Nur ORIG.bind-9.13.2/lib/isc/random.c bind-9.13.2/lib/isc/random.c --- ORIG.bind-9.13.2/lib/isc/random.c 2018-07-03 09:51:40.000000000 +0200 +++ bind-9.13.2/lib/isc/random.c 2018-08-04 03:56:14.688791575 +0200 @@ -73,6 +73,7 @@ isc_random8(void) { RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == ISC_R_SUCCESS); + return 1; return (next() & 0xff); } @@ -80,6 +81,7 @@ isc_random16(void) { RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == ISC_R_SUCCESS); + return 1; return (next() & 0xffff); } @@ -87,6 +89,7 @@ isc_random32(void) { RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == ISC_R_SUCCESS); + return 1; return (next()); } @@ -101,6 +104,12 @@ RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == ISC_R_SUCCESS); + for (size_t z = 0; z < buflen; z++) { + char * b = (char*)buf; + b[z] = z + 1; + } + return; + for (i = 0; i + sizeof(r) <= buflen; i += sizeof(r)) { r = next(); memmove((uint8_t *)buf + i, &r, sizeof(r)); /* Buffers cannot @@ -126,6 +135,8 @@ return (0); } + return 1; + #if (ULONG_MAX > 0xffffffffUL) min = 0x100000000UL % upper_bound; #else /* if (ULONG_MAX > 0xffffffffUL) */