From: Arthur Chan Date: Wed, 17 Jun 2026 17:47:54 +0000 (+0100) Subject: OSS-Fuzz: Add fuzzer targets dnsdist logic X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0aa2b907d7b6b7c72cf778960bdbdd3df67fbb48;p=thirdparty%2Fpdns.git OSS-Fuzz: Add fuzzer targets dnsdist logic Signed-off-by: Arthur Chan --- diff --git a/pdns/dnsdistdist/fuzz_dnsdist_ecs.cc b/pdns/dnsdistdist/fuzz_dnsdist_ecs.cc new file mode 100644 index 0000000000..3521a7cfe8 --- /dev/null +++ b/pdns/dnsdistdist/fuzz_dnsdist_ecs.cc @@ -0,0 +1,100 @@ +/* + * 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 + +#include "dnsdist-ecs.hh" +#include "dnsname.hh" +#include "dns.hh" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (size > std::numeric_limits::max()) { + return 0; + } + + const PacketBuffer packet(data, data + size); + + // Wire-format EDNS/OPT parsing on the raw packet. + try { + EDNS0Record edns0{}; + getEDNS0Record(packet, edns0); + } + catch (...) { + } + + try { + uint16_t optStart = 0; + size_t optLen = 0; + bool last = false; + if (locateEDNSOptRR(packet, &optStart, &optLen, &last) == 0) { + size_t optContentStart = 0; + uint16_t optContentLen = 0; + isEDNSOptionInOpt(packet, optStart, optLen, EDNSOptionCode::ECS, + &optContentStart, &optContentLen); + } + } + catch (...) { + } + + try { + PacketBuffer newContent; + rewriteResponseWithoutEDNS(packet, newContent); + } + catch (...) { + } + + try { + PacketBuffer newContent; + rewriteResponseWithoutEDNSOption(packet, EDNSOptionCode::ECS, newContent); + } + catch (...) { + } + + // ECS add/replace; needs the question name's wire length. + try { + uint16_t qtype = 0; + uint16_t qclass = 0; + unsigned int consumed = 0; + const DNSName qname(reinterpret_cast(data), size, + sizeof(dnsheader), false, &qtype, &qclass, &consumed); + + uint16_t optRDPosition = 0; + size_t remaining = 0; + dnsdist::getEDNSOptionsStart(packet, consumed, &optRDPosition, &remaining); + + PacketBuffer mutablePacket(packet); + bool ednsAdded = false; + bool ecsAdded = false; + std::string newECSOption; + const ComboAddress source("192.0.2.1"); + generateECSOption(source, newECSOption, 24); + handleEDNSClientSubnet(mutablePacket, mutablePacket.size() + 512, consumed, + ednsAdded, ecsAdded, true, newECSOption); + } + catch (...) { + } + + return 0; +} diff --git a/pdns/dnsdistdist/meson.build b/pdns/dnsdistdist/meson.build index 82cec6f472..775fdfcea0 100644 --- a/pdns/dnsdistdist/meson.build +++ b/pdns/dnsdistdist/meson.build @@ -508,6 +508,15 @@ if get_option('fuzz-targets') ], 'fuzzing-target': true, }, + 'fuzz-target-dnsdist-ecs' : { + 'main': src_dir / 'fuzz_dnsdist_ecs.cc', + 'link-args': fuzzer_ldflags, + 'files-extra': fuzz_extra_sources, + 'deps-extra': [ + dep_libsystemd, + ], + 'fuzzing-target': true, + }, } if get_option('xsk').allowed() and dep_libbpf.found() and dep_libxdp.found() tools += {