summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Štetiar2020-10-13 12:36:44 +0000
committerPetr Štetiar2020-10-13 13:27:49 +0000
commit134afc7288461bf0ef0506dfd5430bf28de0880c (patch)
tree126236e19da83475785be70f9bd01f8d65a9b992
parentde08a2c71ca83e783ab6cfc2bb6dda07b25bf381 (diff)
downloadmdnsd-134afc7288461bf0ef0506dfd5430bf28de0880c.tar.gz
tests: add libFuzzer based fuzzing
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>
-rw-r--r--CMakeLists.txt5
-rw-r--r--tests/CMakeLists.txt3
-rw-r--r--tests/fuzz/CMakeLists.txt18
-rw-r--r--tests/fuzz/dict/mdns.dict6
-rw-r--r--tests/fuzz/inputs/query_qu.pcapbin0 -> 128 bytes
-rw-r--r--tests/fuzz/test-fuzz.c48
6 files changed, 80 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e087203..80d1cf5 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 0000000..02b121c
--- /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 0000000..e2f9873
--- /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 0000000..f8f80c1
--- /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 0000000..b1857a9
--- /dev/null
+++ b/tests/fuzz/inputs/query_qu.pcap
Binary files differ
diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 0000000..ca6caa1
--- /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;
+}