Compare commits
1 Commits
v9.11.29
...
honggfuzz-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8e717fc2f |
@@ -33,10 +33,6 @@
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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 mocks. Since AFL for now only
|
||||
@@ -314,7 +310,6 @@ fuzz_main_resolver(void *arg) {
|
||||
* It's here just for the signature, that's how AFL detects if it's
|
||||
* a 'persistent mode' binary.
|
||||
*/
|
||||
__AFL_LOOP(0);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
@@ -437,7 +432,9 @@ named_fuzz_notify(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
raise(SIGSTOP);
|
||||
#endif
|
||||
|
||||
RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0);
|
||||
|
||||
@@ -450,8 +447,7 @@ named_fuzz_notify(void) {
|
||||
|
||||
void
|
||||
named_fuzz_setup(void) {
|
||||
#ifdef ENABLE_AFL
|
||||
if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) {
|
||||
#if 0
|
||||
pthread_t thread;
|
||||
void *(fn) = NULL;
|
||||
|
||||
@@ -475,6 +471,5 @@ named_fuzz_setup(void) {
|
||||
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 */
|
||||
}
|
||||
|
||||
254
bin/named/main.c
254
bin/named/main.c
@@ -1390,13 +1390,255 @@ ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
|
||||
}
|
||||
#endif /* HAVE_LIBSCF */
|
||||
|
||||
#include <named/globals.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libhfcommon/util.h>
|
||||
#include <libhfuzz/libhfuzz.h>
|
||||
|
||||
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 (!ns_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;
|
||||
}
|
||||
|
||||
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 = (void *)rbuf,
|
||||
.iov_len = rlen,
|
||||
},
|
||||
};
|
||||
|
||||
if (writev(nfd, iov, 3) == -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 (!ns_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")) {
|
||||
ns_g_fuzz_named_addr = "127.0.0.1:53";
|
||||
ns_g_fuzz_type = ns_fuzz_client;
|
||||
enter_namespaces();
|
||||
launch_thr();
|
||||
}
|
||||
|
||||
isc_result_t result;
|
||||
#ifdef HAVE_LIBSCF
|
||||
char *instance = NULL;
|
||||
char *instance = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GPERFTOOLS_PROFILER
|
||||
@@ -1439,17 +1681,17 @@ main(int argc, char *argv[]) {
|
||||
|
||||
parse_command_line(argc, argv);
|
||||
|
||||
#ifdef ENABLE_AFL
|
||||
#if 0
|
||||
if (ns_g_fuzz_type != ns_fuzz_none) {
|
||||
named_fuzz_setup();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ns_g_fuzz_type == ns_fuzz_resolver) {
|
||||
dns_resolver_setfuzzing();
|
||||
} else if (ns_g_fuzz_type == ns_fuzz_http) {
|
||||
isc_httpd_setfinishhook(named_fuzz_notify);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Warn about common configuration error.
|
||||
*/
|
||||
|
||||
@@ -8803,7 +8803,7 @@ run_server(isc_task_t *task, isc_event_t *event) {
|
||||
isc_hash_init();
|
||||
|
||||
CHECKFATAL(load_zones(server, ISC_TRUE, ISC_FALSE), "loading zones");
|
||||
#ifdef ENABLE_AFL
|
||||
#if 1
|
||||
ns_g_run_done = ISC_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
25
honggfuzz-compile.sh
Normal file
25
honggfuzz-compile.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
export CC=hfuzz-clang
|
||||
export CXX=hfuzz-clang++
|
||||
export CFLAGS="-fsanitize=address,undefined -Wno-shift-negative-value -Wno-logical-not-parentheses -g -ggdb -O0"
|
||||
./configure \
|
||||
--prefix=/opt/bind-9.11.4/ \
|
||||
--enable-threads \
|
||||
--without-gssapi \
|
||||
--disable-chroot \
|
||||
--disable-linux-caps \
|
||||
--disable-seccomp \
|
||||
--with-libtool \
|
||||
--enable-ipv6 \
|
||||
--enable-atomic \
|
||||
--enable-epoll \
|
||||
--enable-afl \
|
||||
--disable-crypto-rand \
|
||||
--disable-backtrace \
|
||||
--with-openssl=yes
|
||||
|
||||
make clean
|
||||
make -j$(nproc)
|
||||
@@ -812,6 +812,7 @@ dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
|
||||
|
||||
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
|
||||
tcp = ISC_TRUE;
|
||||
tcp = ISC_TRUE;
|
||||
share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
|
||||
|
||||
again:
|
||||
@@ -1137,6 +1138,8 @@ static isc_result_t
|
||||
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;
|
||||
@@ -1193,9 +1196,10 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp,
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1670,6 +1670,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
}
|
||||
query->mctx = fctx->mctx;
|
||||
query->options = options;
|
||||
query->options = options | DNS_FETCHOPT_TCP;
|
||||
query->attributes = 0;
|
||||
query->sends = 0;
|
||||
query->connects = 0;
|
||||
|
||||
@@ -123,12 +123,17 @@ isc_random_seed(isc_uint32_t seed) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static isc_uint32_t RND = 1;
|
||||
|
||||
void
|
||||
isc_random_get(isc_uint32_t *val) {
|
||||
REQUIRE(val != NULL);
|
||||
|
||||
initialize();
|
||||
|
||||
*val = RND;
|
||||
return;
|
||||
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
/*
|
||||
* rand()'s lower bits are not random.
|
||||
@@ -367,6 +372,8 @@ isc_rng_random(isc_rng_t *rng) {
|
||||
|
||||
REQUIRE(VALID_RNG(rng));
|
||||
|
||||
return (1);
|
||||
|
||||
LOCK(&rng->lock);
|
||||
|
||||
rng->count -= sizeof(isc_uint16_t);
|
||||
@@ -388,6 +395,8 @@ isc_rng_uniformrandom(isc_rng_t *rng, isc_uint16_t upper_bound) {
|
||||
if (upper_bound < 2)
|
||||
return (0);
|
||||
|
||||
return RND % upper_bound;
|
||||
|
||||
/*
|
||||
* Ensure the range of random numbers [min, 0xffff] be a multiple of
|
||||
* upper_bound and contain at least a half of the 16 bit range.
|
||||
|
||||
Reference in New Issue
Block a user