From: Remi Gacogne Date: Tue, 22 May 2018 22:26:23 +0000 (+0200) Subject: Add fuzzing targets X-Git-Tag: auth-4.2.0-alpha1~6^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=af6f3d536b365b606ee7c671db6514c165a876e1;p=thirdparty%2Fpdns.git Add fuzzing targets --- diff --git a/configure.ac b/configure.ac index 0bdb48e30c..ce85a2f160 100644 --- a/configure.ac +++ b/configure.ac @@ -118,6 +118,7 @@ AS_IF([test "$boost_cv_lib_program_options" = "no"], [ PDNS_ENABLE_UNIT_TESTS PDNS_ENABLE_BACKEND_UNIT_TESTS PDNS_ENABLE_REPRODUCIBLE +PDNS_ENABLE_FUZZ_TARGETS PDNS_WITH_SQLITE3 diff --git a/m4/pdns_enable_fuzz_targets.m4 b/m4/pdns_enable_fuzz_targets.m4 new file mode 100644 index 0000000000..9973fd93ec --- /dev/null +++ b/m4/pdns_enable_fuzz_targets.m4 @@ -0,0 +1,11 @@ +AC_DEFUN([PDNS_ENABLE_FUZZ_TARGETS], [ + AC_MSG_CHECKING([whether to enable fuzzing targets]) + AC_ARG_ENABLE([fuzz_targets], + AS_HELP_STRING([--enable-fuzz-targets], + [enable fuzz targets @<:@default=no@:>@]), + [enable_fuzz_targets=$enableval], + [enable_fuzz_targets=no] + ) + AC_MSG_RESULT([$enable_fuzz_targets]) + AM_CONDITIONAL([FUZZ_TARGETS], [test "x$enable_fuzz_targets" != "xno"]) +]) diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 974c70083c..76d93b5bd2 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -1370,6 +1370,111 @@ check-local: @echo "Run ./configure --enable-unit-tests" endif +if FUZZ_TARGETS + +LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o + +standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cc + +bin_PROGRAMS += \ + fuzz_dnsdistcache \ + fuzz_moadnsparser \ + fuzz_packetcache \ + fuzz_zoneparsertng + +fuzz_targets_libs = \ + $(LIBCRYPTO_LIBS) \ + $(LIB_FUZZING_ENGINE) +fuzz_targets_ldflags = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(FUZZING_LDFLAGS) + +# we need the mockup runner to be built, but not linked if a real fuzzing engine is used +fuzz_targets_deps = standalone_fuzz_target_runner.o + +fuzz_moadnsparser_SOURCES = \ + fuzz_moadnsparser.cc \ + base32.cc base32.hh \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc dnsrecords.hh \ + dnswriter.cc dnswriter.hh \ + logger.cc logger.hh \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc statbag.hh \ + unix_utility.cc \ + utility.hh + +fuzz_moadnsparser_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_moadnsparser_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_moadnsparser_LDADD = $(fuzz_targets_libs) + +fuzz_packetcache_SOURCES = \ + fuzz_packetcache.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + ednsoptions.cc ednsoptions.hh \ + misc.cc misc.hh \ + packetcache.hh \ + statbag.cc statbag.hh + +fuzz_packetcache_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_packetcache_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_packetcache_LDADD = $(fuzz_targets_libs) + +fuzz_dnsdistcache_SOURCES = \ + fuzz_dnsdistcache.cc \ + dnsdist-cache.cc dnsdist-cache.hh \ + dnsdist-ecs.cc dnsdist-ecs.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc iputils.hh \ + misc.cc misc.hh \ + packetcache.hh \ + qtype.cc qtype.hh + +fuzz_dnsdistcache_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_dnsdistcache_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_dnsdistcache_LDADD = $(fuzz_targets_libs) + +fuzz_zoneparsertng_SOURCES = \ + fuzz_zoneparsertng.cc \ + base32.cc base32.hh \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc dnsrecords.hh \ + dnswriter.cc dnswriter.hh \ + logger.cc logger.hh \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc statbag.hh \ + unix_utility.cc \ + utility.hh \ + zoneparser-tng.cc zoneparser-tng.hh + +fuzz_zoneparsertng_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_zoneparsertng_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_zoneparsertng_LDADD = $(fuzz_targets_libs) + +endif + dnslabeltext.cc: dnslabeltext.rl $(AM_V_GEN)$(RAGEL) $< -o dnslabeltext.cc diff --git a/pdns/dnsdist-cache.hh b/pdns/dnsdist-cache.hh index 14902c400c..8f16f03868 100644 --- a/pdns/dnsdist-cache.hh +++ b/pdns/dnsdist-cache.hh @@ -23,6 +23,8 @@ #include #include + +#include "iputils.hh" #include "lock.hh" struct DNSQuestion; @@ -54,6 +56,7 @@ public: static uint32_t getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA); static uint32_t getKey(const std::string& qname, uint16_t consumed, const unsigned char* packet, uint16_t packetLen, bool tcp); + static bool getClientSubnet(const char* packet, unsigned int consumed, uint16_t len, boost::optional& subnet); private: @@ -95,7 +98,6 @@ private: std::atomic d_entriesCount; }; - static bool getClientSubnet(const char* packet, unsigned int consumed, uint16_t len, boost::optional& subnet); bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, bool dnssecOK, const boost::optional& subnet) const; uint32_t getShardIndex(uint32_t key) const; void insertLocked(CacheShard& shard, uint32_t key, CacheValue& newValue); diff --git a/pdns/fuzz_dnsdistcache.cc b/pdns/fuzz_dnsdistcache.cc new file mode 100644 index 0000000000..d9c8efa717 --- /dev/null +++ b/pdns/fuzz_dnsdistcache.cc @@ -0,0 +1,43 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-cache.hh" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + + /* dnsdist's version */ + try { + uint16_t qtype; + uint16_t qclass; + unsigned int consumed; + DNSName qname(reinterpret_cast(data), size, sizeof(dnsheader), false, &qtype, &qclass, &consumed); + DNSDistPacketCache::getKey(qname.toString(), consumed, data, size, false); + boost::optional subnet; + DNSDistPacketCache::getClientSubnet(reinterpret_cast(data), consumed, size, subnet); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_moadnsparser.cc b/pdns/fuzz_moadnsparser.cc new file mode 100644 index 0000000000..cf9660ec7d --- /dev/null +++ b/pdns/fuzz_moadnsparser.cc @@ -0,0 +1,59 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsparser.hh" +#include "dnsrecords.hh" +#include "statbag.hh" + +StatBag S; + +static void init() +{ + reportAllTypes(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static bool initialized = false; + + if (!initialized) { + init(); + initialized = true; + } + + try { + MOADNSParser moaQuery(true, reinterpret_cast(data), size); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + try { + MOADNSParser moaAnswer(false, reinterpret_cast(data), size); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_packetcache.cc b/pdns/fuzz_packetcache.cc new file mode 100644 index 0000000000..b8d9f22616 --- /dev/null +++ b/pdns/fuzz_packetcache.cc @@ -0,0 +1,53 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "packetcache.hh" +#include "statbag.hh" + +StatBag S; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + + std::string input(reinterpret_cast(data), size); + + /* auth's version */ + try { + PacketCache::canHashPacket(input); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + /* recursor's version */ + try { + uint16_t ecsBegin = 0; + uint16_t ecsEnd = 0; + PacketCache::canHashPacket(input, &ecsBegin, &ecsEnd); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_zoneparsertng.cc b/pdns/fuzz_zoneparsertng.cc new file mode 100644 index 0000000000..a6f30d3859 --- /dev/null +++ b/pdns/fuzz_zoneparsertng.cc @@ -0,0 +1,60 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsname.hh" +#include "dnsparser.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "zoneparser-tng.hh" + +StatBag S; + +static void init() +{ + reportAllTypes(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static bool initialized = false; + + if (!initialized) { + init(); + initialized = true; + } + + try { + std::vector lines; + std::string tmp(reinterpret_cast(data), size); + boost::split(lines, tmp, boost::is_any_of("\n")); + + ZoneParserTNG zpt(lines, g_rootdnsname); + DNSResourceRecord drr; + while (zpt.get(drr)) { + } + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/standalone_fuzz_target_runner.cc b/pdns/standalone_fuzz_target_runner.cc new file mode 100644 index 0000000000..1de874f5c3 --- /dev/null +++ b/pdns/standalone_fuzz_target_runner.cc @@ -0,0 +1,51 @@ + +#include +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); +extern "C" __attribute__((weak)) int LLVMFuzzerInitialize(int* argc, char*** argv); + +int main(int argc, char** argv) +{ + std::cerr<<"StandaloneFuzzTargetMain: running "<<(argc-1)<<" inputs"< buffer; + buffer.resize(fileSize); + + file.read(reinterpret_cast(buffer.data()), fileSize); + + if (file.fail()) { + file.close(); + throw std::runtime_error("Error reading fuzzing input from file '" + std::string(argv[i]) + '"'); + } + + file.close(); + + LLVMFuzzerTestOneInput(reinterpret_cast(buffer.data()), fileSize); + + std::cerr<<"Done: '"<