From: Tomek Mrugalski Date: Mon, 21 Nov 2016 12:22:58 +0000 (+0100) Subject: [experiments/fuzz] Documentation updated. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a9d94f47ce0dda490756cca291a10c83190af0f0;p=thirdparty%2Fkea.git [experiments/fuzz] Documentation updated. --- diff --git a/doc/fuzz.txt b/doc/fuzz.txt index 5f55e30054..533e06aa4e 100644 --- a/doc/fuzz.txt +++ b/doc/fuzz.txt @@ -15,8 +15,8 @@ Ubuntu 16.04 I had to do this: 3. Set up path to AFL binaries - EXPORT AFL_PATH=/home/thomson/devel/afl-2.35b - EXPORT PATH=$PATH:/home/thomson/devel/afl-2.35b + export AFL_PATH=/home/thomson/devel/afl-2.35b + export PATH=$PATH:/home/thomson/devel/afl-2.35b 4. Build Kea using AFL @@ -24,13 +24,13 @@ Ubuntu 16.04 I had to do this: git pull git checkout experiments/fuzz autoreconf -i - CXX=afl-clang-fast++ ./configure --enable-fuzz + CXX=afl-clang-fast++ ./configure --enable-fuzz --enable-static-link make Note: no unit-tests needed. We will be fuzzing the production code only. -5. Run fuzzer +5. Configure destination address The defaults (see src/bin/dhcp6/fuzz.cc) are: interface: eth0 @@ -45,4 +45,31 @@ Ubuntu 16.04 I had to do this: E.g. export KEA_AFL_INTERFACE=eth1 - +6. Run fuzzer + + Set up max size of a virtual memory allowed to 4GB: + ulimit -v 4096000 + + Instruct AFL to allow 4096MB of virtual memory and run AFL: + afl-fuzz -m 4096 -i tests/fuzz-data -o fuzz-out ./kea-dhcp6 -c fuzz.json + + Here's what the switches do: + -m 4096 - allow Kea to take up to 4GB memory + -i tests/fuzz-data - Input seeds. These are the packet files used + to initiate the packet randomization. Several examples are in + src/bin/dhcp6/tests/fuzz-data. You can extract them using wireshark, + right click on a packet, then export as binary data. Make sure you + export the payload of UDP content. the first exported byte should + by message-type. + -o dir - that's the output directory. It doesn't have to exist. + +7. Checking that the fuzzer is really working + + a) the harness prints out a line to /tmp/kea-fuzz-harness.txt every + time a new packet is sent. This generated 4,5MB of entries in 20 + minutes. Obviously, this has to be disabled for production fuzzing, + but it's good for initial trials. + + b) I have my fuzz.json (which is renamed doc/examples/kea6/simple.json) + that tell Kea to use logging on level INFO and write output to a + file. This file keeps growing. That's around 3,8MB after 20 minutes. diff --git a/src/bin/dhcp6/fuzz.cc b/src/bin/dhcp6/fuzz.cc index 2e8be8f0c3..43071b138e 100644 --- a/src/bin/dhcp6/fuzz.cc +++ b/src/bin/dhcp6/fuzz.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include + #ifndef __AFL_LOOP #error To use American Fuzzy Lop you have to set CC to afl-clang-fast!!! #endif @@ -59,6 +61,8 @@ kea_main_client(void *arg) { string dst(ALL_DHCP_RELAY_AGENTS_AND_SERVERS); string port("547"); + ofstream f("/tmp/kea-fuzz-harness.txt", ios::ate); + const char *iface_ptr = getenv("KEA_AFL_INTERFACE"); if (iface_ptr) { iface = string(iface_ptr); @@ -76,17 +80,17 @@ kea_main_client(void *arg) { unsigned int iface_id = if_nametoindex(iface.c_str()); - cout << "Kea AFL setup:" << endl; - cout << "Interface: " << iface << endl; - cout << "Interface index: " << iface_id << endl; - cout << "UDP destination addr: " << dst << endl; - cout << "UDP destination port: " << port << endl; + f << "Kea AFL setup:" << endl; + f << "Interface: " << iface << endl; + f << "Interface index: " << iface_id << endl; + f << "UDP destination addr: " << dst << endl; + f << "UDP destination port: " << port << endl; memset(&servaddr, 0, sizeof (servaddr)); servaddr.sin6_family = AF_INET6; if (inet_pton(AF_INET6, dst.c_str(), &servaddr.sin6_addr) != 1) { - cout << "Error: inet_pton() failed: can't convert " << dst - << " to address." << endl; + f << "Error: inet_pton() failed: can't convert " << dst + << " to address." << endl; exit(EXIT_FAILURE); } servaddr.sin6_port = htons(547); @@ -94,13 +98,13 @@ kea_main_client(void *arg) { sockfd = socket(AF_INET6, SOCK_DGRAM, 0); if (sockfd < 0) { - cout << "Failed to create UDP6 socket" << endl; + f << "Failed to create UDP6 socket" << endl; exit(EXIT_FAILURE); } buf = malloc(65536); if (!buf) { - cout << "Failed to allocate a buffer" << endl; + f << "Failed to allocate a buffer" << endl; exit(EXIT_FAILURE); } @@ -126,21 +130,21 @@ kea_main_client(void *arg) { } */ if (pthread_mutex_lock(&mutex) != 0) { - cout << "#### Failed to lock mutex" << endl; + f << "#### Failed to lock mutex" << endl; } ready = false; ssize_t sent; - cout << "Sending " << length << " bytes to " << dst << "/" << port - << " over " << iface << "/" << iface_id << endl; + f << "Sending " << length << " bytes to " << dst << "/" << port + << " over " << iface << "/" << iface_id << endl; sent = sendto(sockfd, buf, length, 0, (struct sockaddr *) &servaddr, sizeof(servaddr)); if (sent != length) { - cout << "#### Error: expected to send " << length - << ", but really sent " << sent << endl; + f << "#### Error: expected to send " << length + << ", but really sent " << sent << endl; } /* unclog */ @@ -150,7 +154,7 @@ kea_main_client(void *arg) { pthread_cond_wait(&cond, &mutex); if (pthread_mutex_unlock(&mutex) != 0) { - cout << "#### Failed to unlock mutex" << endl; + f << "#### Failed to unlock mutex" << endl; } }