1diff --git a/configure.ac b/configure.ac 2index 7975d31..528861c 100644 3--- a/configure.ac 4+++ b/configure.ac 5@@ -4399,6 +4399,37 @@ AC_DEFINE_UNQUOTED([DYNAMIC_INTERLEAVE], [$ntp_dynamic_interleave], 6 [support dynamic interleave?]) 7 AC_MSG_RESULT([$ntp_ok]) 8 9+AC_ARG_ENABLE(fuzztargets, 10+ AS_HELP_STRING([--enable-fuzztargets], [Enable fuzz targets]),[enable_fuzztargets=$enableval],[enable_fuzztargets=no]) 11+AM_CONDITIONAL([BUILD_FUZZTARGETS], [test "x$enable_fuzztargets" = "xyes"]) 12+AS_IF([test "x$enable_fuzztargets" = "xyes"], [ 13+ AC_PROG_CXX 14+ AC_LANG_PUSH(C++) 15+ AS_IF([test "x$LIB_FUZZING_ENGINE" = "x"], [ 16+ LIB_FUZZING_ENGINE=-fsanitize=fuzzer 17+ AC_SUBST(LIB_FUZZING_ENGINE) 18+ ]) 19+ tmp_saved_flags=$[]_AC_LANG_PREFIX[]FLAGS 20+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $LIB_FUZZING_ENGINE" 21+ AC_MSG_CHECKING([whether $CXX accepts $LIB_FUZZING_ENGINE]) 22+ AC_LINK_IFELSE([AC_LANG_SOURCE([[ 23+#include <sys/types.h> 24+extern "C" int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); 25+extern "C" int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size) { 26+(void)Data; 27+(void)Size; 28+return 0; 29+} 30+ ]])], 31+ [ AC_MSG_RESULT(yes) 32+ has_sanitizefuzzer=yes], 33+ [ AC_MSG_RESULT(no) ] 34+ ) 35+ _AC_LANG_PREFIX[]FLAGS=$tmp_saved_flags, [] 36+ AC_LANG_POP() 37+]) 38+AM_CONDITIONAL([HAS_SANITIZEFUZZER], [test "x$has_sanitizefuzzer" = "xyes"]) 39+ 40 NTP_UNITYBUILD 41 42 dnl gtest is needed for our tests subdirs. It would be nice if we could 43@@ -4459,6 +4490,7 @@ AC_CONFIG_FILES([tests/ntpd/Makefile]) 44 AC_CONFIG_FILES([tests/ntpq/Makefile]) 45 AC_CONFIG_FILES([tests/sandbox/Makefile]) 46 AC_CONFIG_FILES([tests/sec-2853/Makefile]) 47+AC_CONFIG_FILES([tests/fuzz/Makefile]) 48 AC_CONFIG_FILES([util/Makefile]) 49 50 perllibdir="${datadir}/ntp/lib" 51diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c 52index 7c3fdd4..190a373 100644 53--- a/ntpd/ntp_io.c 54+++ b/ntpd/ntp_io.c 55@@ -503,7 +503,11 @@ io_open_sockets(void) 56 * Create the sockets 57 */ 58 BLOCKIO(); 59+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 60+ create_sockets(4123); 61+#else 62 create_sockets(NTP_PORT); 63+#endif 64 UNBLOCKIO(); 65 66 init_async_notifications(); 67diff --git a/tests/Makefile.am b/tests/Makefile.am 68index af502b9..60a2379 100644 69--- a/tests/Makefile.am 70+++ b/tests/Makefile.am 71@@ -10,3 +10,6 @@ SUBDIRS += \ 72 sec-2853 \ 73 $(NULL) 74 75+if BUILD_FUZZTARGETS 76+ SUBDIRS += fuzz 77+endif 78diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am 79new file mode 100644 80index 0000000..7f482b5 81--- /dev/null 82+++ b/tests/fuzz/Makefile.am 83@@ -0,0 +1,13 @@ 84+include $(top_srcdir)/includes.mf 85+ 86+bin_PROGRAMS = fuzz_ntpd_receive 87+ 88+fuzz_ntpd_receive_SOURCES = fuzz_ntpd_receive.c ../../ntpd/ntp_io.c ../../ntpd/ntp_config.c ../../ntpd/ntp_scanner.c ../../ntpd/ntp_parser.y ../../ntpd/ntpd-opts.c 89+fuzz_ntpd_receive_CFLAGS = $(NTP_INCS) -I../../sntp/libopts -I../../ntpd/ 90+fuzz_ntpd_receive_LDADD = ../../ntpd/libntpd.a $(LIBPARSE) ../../libntp/libntp.a $(LDADD_LIBNTP) $(LIBOPTS_LDADD) $(PTHREAD_LIBS) $(LIBM) $(LDADD_NTP) $(LSCF) $(LDADD_LIBUTIL) 91+ 92+if HAS_SANITIZEFUZZER 93+ fuzz_ntpd_receive_LDFLAGS = $(LIB_FUZZING_ENGINE) -lstdc++ -stdlib=libc++ 94+else 95+ fuzz_ntpd_receive_SOURCES += onefile.c 96+endif 97diff --git a/tests/fuzz/fuzz_ntpd_receive.c b/tests/fuzz/fuzz_ntpd_receive.c 98new file mode 100644 99index 0000000..7cb8d99 100--- /dev/null 101+++ b/tests/fuzz/fuzz_ntpd_receive.c 102@@ -0,0 +1,94 @@ 103+#include <stddef.h> 104+#include <stdint.h> 105+#include <sys/types.h> 106+#include <sys/stat.h> 107+#include <fcntl.h> 108+ 109+#include "config.h" 110+#include "recvbuff.h" 111+#include "ntpd.h" 112+ 113+const char *Version = "libntpq 0.3beta"; 114+int listen_to_virtual_ips = TRUE; 115+int mdnstries = 5; 116+char const *progname = "fuzz_ntpd_receive"; 117+#ifdef HAVE_WORKING_FORK 118+int waitsync_fd_to_close = -1; /* -w/--wait-sync */ 119+#endif 120+int yydebug=0; 121+ 122+static int initialized = 0; 123+int sockfd; 124+uint8_t itf_index; 125+ 126+void fuzz_itf_selecter(void * data, interface_info_t * itf) { 127+ endpt **ep = (endpt **)data; 128+ if (itf_index == 0) { 129+ *ep = itf->ep; 130+ } 131+ itf_index--; 132+} 133+ 134+int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { 135+ struct recvbuf rbufp; 136+ 137+ if (initialized == 0) { 138+ sockfd = open("/dev/null", O_RDWR ); 139+ //adds interfaces 140+ init_io(); 141+ init_auth(); 142+ init_util(); 143+ init_restrict(); 144+ init_mon(); 145+ init_timer(); 146+ init_lib(); 147+ init_request(); 148+ init_control(); 149+ init_peer(); 150+ init_proto(); 151+ init_loopfilter(); 152+ io_open_sockets(); 153+ initialized = 1; 154+ } 155+ 156+ if (Size < sizeof(l_fp)) { 157+ return 0; 158+ } 159+ memcpy(&rbufp.recv_time, Data, sizeof(l_fp)); 160+ Data += sizeof(l_fp); 161+ Size -= sizeof(l_fp); 162+ 163+ if (Size < sizeof(sockaddr_u)) { 164+ return 0; 165+ } 166+ memcpy(&rbufp.srcadr, Data, sizeof(sockaddr_u)); 167+ memcpy(&rbufp.recv_srcadr, &rbufp.srcadr, sizeof(sockaddr_u)); 168+ Data += sizeof(sockaddr_u); 169+ Size -= sizeof(sockaddr_u); 170+ 171+ if (Size < 1) { 172+ return 0; 173+ } 174+ itf_index = Data[0]; 175+ rbufp.dstadr = NULL; 176+ interface_enumerate(fuzz_itf_selecter, &rbufp.dstadr); 177+ if (rbufp.dstadr == NULL) { 178+ return 0; 179+ } 180+ Data++; 181+ Size--; 182+ 183+ if (Size > RX_BUFF_SIZE) { 184+ Size = RX_BUFF_SIZE; 185+ } 186+ rbufp.recv_length = Size; 187+ memcpy(rbufp.recv_buffer, Data, Size); 188+ 189+ rbufp.msg_flags = 0; 190+ rbufp.used = 0; 191+ rbufp.link = NULL; 192+ rbufp.fd = sockfd; 193+ 194+ receive(&rbufp); 195+ return 0; 196+} 197diff --git a/tests/fuzz/onefile.c b/tests/fuzz/onefile.c 198new file mode 100644 199index 0000000..74be306 200--- /dev/null 201+++ b/tests/fuzz/onefile.c 202@@ -0,0 +1,51 @@ 203+#include <stdint.h> 204+#include <stdlib.h> 205+#include <stdio.h> 206+ 207+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 208+ 209+int main(int argc, char** argv) 210+{ 211+ FILE * fp; 212+ uint8_t *Data; 213+ size_t Size; 214+ 215+ if (argc != 2) { 216+ return 1; 217+ } 218+ //opens the file, get its size, and reads it into a buffer 219+ fp = fopen(argv[1], "rb"); 220+ if (fp == NULL) { 221+ return 2; 222+ } 223+ if (fseek(fp, 0L, SEEK_END) != 0) { 224+ fclose(fp); 225+ return 2; 226+ } 227+ Size = ftell(fp); 228+ if (Size == (size_t) -1) { 229+ fclose(fp); 230+ return 2; 231+ } 232+ if (fseek(fp, 0L, SEEK_SET) != 0) { 233+ fclose(fp); 234+ return 2; 235+ } 236+ Data = malloc(Size); 237+ if (Data == NULL) { 238+ fclose(fp); 239+ return 2; 240+ } 241+ if (fread(Data, Size, 1, fp) != 1) { 242+ fclose(fp); 243+ free(Data); 244+ return 2; 245+ } 246+ 247+ //lauch fuzzer 248+ LLVMFuzzerTestOneInput(Data, Size); 249+ free(Data); 250+ fclose(fp); 251+ return 0; 252+} 253+ 254