diff mbox series

[mdnsd,06/10] tests: add libFuzzer based fuzzing

Message ID 20201013133621.27088-7-ynezz@true.cz
State Accepted
Delegated to: Petr Štetiar
Headers show
Series fixes and improvements | expand

Commit Message

Petr Štetiar Oct. 13, 2020, 1:36 p.m. UTC
LibFuzzer is in-process, coverage-guided, evolutionary fuzzing engine.

LibFuzzer is linked with the library under test, and feeds fuzzed inputs
to the library via a specific fuzzing entrypoint (aka "target
function"); the fuzzer then tracks which areas of the code are reached,
and generates mutations on the corpus of input data in order to maximize
the code coverage.

So lets use libFuzzer to fuzz dns_handle_packet for the start.

Ref: https://llvm.org/docs/LibFuzzer.html
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
 CMakeLists.txt                  |   5 ++++
 tests/CMakeLists.txt            |   3 ++
 tests/fuzz/CMakeLists.txt       |  18 ++++++++++++
 tests/fuzz/dict/mdns.dict       |   6 ++++
 tests/fuzz/inputs/query_qu.pcap | Bin 0 -> 128 bytes
 tests/fuzz/test-fuzz.c          |  48 ++++++++++++++++++++++++++++++++
 6 files changed, 80 insertions(+)
 create mode 100644 tests/CMakeLists.txt
 create mode 100644 tests/fuzz/CMakeLists.txt
 create mode 100644 tests/fuzz/dict/mdns.dict
 create mode 100644 tests/fuzz/inputs/query_qu.pcap
 create mode 100644 tests/fuzz/test-fuzz.c
diff mbox series

Patch

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e08720327b7c..80d1cf5be352 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,11 @@  TARGET_LINK_LIBRARIES(umdns-lib ${LIBS})
 ADD_EXECUTABLE(umdns main.c)
 TARGET_LINK_LIBRARIES(umdns umdns-lib)
 
+IF(UNIT_TESTING)
+  ENABLE_TESTING()
+  ADD_SUBDIRECTORY(tests)
+ENDIF()
+
 INSTALL(TARGETS umdns
 	RUNTIME DESTINATION sbin
 )
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 000000000000..02b121c7b8ec
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,3 @@ 
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+  ADD_SUBDIRECTORY(fuzz)
+ENDIF()
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 000000000000..e2f98730de05
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,18 @@ 
+FILE(GLOB test_cases "test-*.c")
+
+MACRO(ADD_FUZZER_TEST name)
+  ADD_EXECUTABLE(${name} ${name}.c)
+  TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+  TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+  TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+  TARGET_LINK_LIBRARIES(${name} umdns-lib-san ${LIBS})
+  ADD_TEST(
+    NAME ${name}
+	COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+  )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FOREACH(test_case ${test_cases})
+  GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+  ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
diff --git a/tests/fuzz/dict/mdns.dict b/tests/fuzz/dict/mdns.dict
new file mode 100644
index 000000000000..f8f80c13a521
--- /dev/null
+++ b/tests/fuzz/dict/mdns.dict
@@ -0,0 +1,6 @@ 
+"\x0c"
+"\x78"
+"\xc0\xb0"
+"\x80\x01"
+"."
+"_"
diff --git a/tests/fuzz/inputs/query_qu.pcap b/tests/fuzz/inputs/query_qu.pcap
new file mode 100644
index 0000000000000000000000000000000000000000..b1857a963a4f3efb0af43ee6714d96f07e04c198
GIT binary patch
literal 128
zcmca|c+)~A1{MYcU}0bca;#!n<JHYr7$Sgd5N2eEV_^8LaBuCt_cJ*dTp1X=RxWd3
z_%C>84i^_!)B~WL$V-uz3}#=K0TqLkg8^rJacWUnW^!sVdwfb>v2Jk+OMGcc0c%cv
Ma$*hx15X1Z0A`FJT>t<8

literal 0
HcmV?d00001

diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 000000000000..ca6caa1ee17a
--- /dev/null
+++ b/tests/fuzz/test-fuzz.c
@@ -0,0 +1,48 @@ 
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "dns.h"
+#include "cache.c"
+#include "interface.h"
+
+int cfg_proto = 0;
+int cfg_no_subnet = 0;
+
+static void fuzz_dns_handle_packet(uint8_t *input, size_t size)
+{
+	struct sockaddr from;
+	struct interface iface;
+	struct cache_service *s, *t;
+
+	memset(&from, 0, sizeof(from));
+	memset(&iface, 0, sizeof(iface));
+
+	cache_init();
+	dns_handle_packet(&iface, &from, 1922, input, size);
+
+	avl_for_each_element_safe(&services, s, avl, t)
+		cache_service_free(s);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *input, size_t size)
+{
+	uint8_t *buf = calloc(1, size);
+	if (!buf)
+		return 0;
+
+	memcpy(buf, input, size);
+	fuzz_dns_handle_packet(buf, size);
+	free(buf);
+
+	return 0;
+}