From: Remi Gacogne Date: Mon, 29 Jan 2024 10:12:27 +0000 (+0100) Subject: dnsdist: Add a fuzzing target for the XSK code X-Git-Tag: dnsdist-1.9.0-rc1^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8c3569cee960fd94aa5b1f6b1fa3967723611b5;p=thirdparty%2Fpdns.git dnsdist: Add a fuzzing target for the XSK code --- diff --git a/fuzzing/corpus/raw-xsk-frames/v4-udp.raw b/fuzzing/corpus/raw-xsk-frames/v4-udp.raw new file mode 100644 index 0000000000..31084b5849 Binary files /dev/null and b/fuzzing/corpus/raw-xsk-frames/v4-udp.raw differ diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index c78fb5a650..d83066e954 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1896,7 +1896,7 @@ bool XskProcessQuery(ClientState& cs, LocalHolders& holders, XskPacket& packet) ids.origDest = dest; ids.hopLocal = dest; ids.protocol = dnsdist::Protocol::DoUDP; - ids.xskPacketHeader = packet.cloneHeadertoPacketBuffer(); + ids.xskPacketHeader = packet.cloneHeaderToPacketBuffer(); try { bool expectProxyProtocol = false; diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 1a1e3080c1..60e76e0ff8 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -519,6 +519,11 @@ standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cc fuzz_targets_programs = \ fuzz_target_dnsdistcache +if HAVE_XSK +fuzz_targets_programs += \ + fuzz_target_xsk +endif + fuzz_targets: $(ARC4RANDOM_LIBS) $(fuzz_targets_programs) bin_PROGRAMS += \ @@ -564,7 +569,21 @@ fuzz_target_dnsdistcache_DEPENDENCIES = $(fuzz_targets_deps) fuzz_target_dnsdistcache_LDFLAGS = $(fuzz_targets_ldflags) fuzz_target_dnsdistcache_LDADD = $(fuzz_targets_libs) -endif +if HAVE_XSK +fuzz_target_xsk_SOURCES = \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + fuzz_xsk.cc \ + gettime.cc gettime.hh \ + iputils.cc iputils.hh \ + misc.cc misc.hh \ + xsk.cc xsk.hh +fuzz_target_xsk_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_target_xsk_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_target_xsk_LDADD = $(fuzz_targets_libs) -lbpf -lxdp +endif # HAVE_XSK + +endif # FUZZ_TARGETS MANPAGES=dnsdist.1 diff --git a/pdns/dnsdistdist/fuzz_xsk.cc b/pdns/dnsdistdist/fuzz_xsk.cc new file mode 100644 index 0000000000..4c67cf45c2 --- /dev/null +++ b/pdns/dnsdistdist/fuzz_xsk.cc @@ -0,0 +1,58 @@ +/* + * 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 "xsk.hh" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ +#ifdef HAVE_XSK + if (size > XskSocket::getFrameSize()) { + return 0; + } + + try { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): packet data is usually mutable + XskPacket packet(const_cast(data), size, size); + if (packet.parse(false)) { + const auto& dest = packet.getToAddr(); + const auto& orig = packet.getFromAddr(); + const auto* payload = packet.getPayloadData(); + auto capacity = packet.getCapacity(); + auto length = packet.getDataLen(); + auto frameLen = packet.getFrameLen(); + auto header = packet.cloneHeaderToPacketBuffer(); + auto buffer = packet.clonePacketBuffer(); + (void) dest; + (void) orig; + (void) payload; + (void) capacity; + (void) length; + (void) frameLen; + } + } + catch (const std::exception& e) { + } +#endif /* HAVE_XSK */ + return 0; +} diff --git a/pdns/xsk.cc b/pdns/xsk.cc index ee05b3a37a..d0cb88513a 100644 --- a/pdns/xsk.cc +++ b/pdns/xsk.cc @@ -150,12 +150,12 @@ XskSocket::XskSocket(size_t frameNum_, std::string ifName_, uint32_t queue_id, c uniqueEmptyFrameOffset.reserve(frameNum); { - for (uint64_t i = 0; i < frameNum; i++) { - uniqueEmptyFrameOffset.push_back(i * frameSize + XDP_PACKET_HEADROOM); + for (uint64_t idx = 0; idx < frameNum; idx++) { + uniqueEmptyFrameOffset.push_back(idx * frameSize + XDP_PACKET_HEADROOM); #ifdef DEBUG_UMEM { auto umems = s_umems.lock(); - (*umems)[i * frameSize + XDP_PACKET_HEADROOM] = UmemEntryStatus(); + (*umems)[idx * frameSize + XDP_PACKET_HEADROOM] = UmemEntryStatus(); } #endif /* DEBUG_UMEM */ } @@ -479,7 +479,7 @@ std::string XskSocket::getMetrics() const } bpf_xdp_query_opts info{}; info.sz = sizeof(info); - int ret = bpf_xdp_query(itfIdx, 0, &info); + int ret = bpf_xdp_query(static_cast(itfIdx), 0, &info); if (ret != 0) { return {}; } @@ -552,7 +552,6 @@ void XskPacket::setEthernetHeader(const ethhdr& ethHeader) noexcept [[nodiscard]] iphdr XskPacket::getIPv4Header() const noexcept { iphdr ipv4Header{}; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) assert(frameLength >= (sizeof(ethhdr) + sizeof(ipv4Header))); assert(!v6); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -562,7 +561,6 @@ void XskPacket::setEthernetHeader(const ethhdr& ethHeader) noexcept void XskPacket::setIPv4Header(const iphdr& ipv4Header) noexcept { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) assert(frameLength >= (sizeof(ethhdr) + sizeof(iphdr))); assert(!v6); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -572,7 +570,6 @@ void XskPacket::setIPv4Header(const iphdr& ipv4Header) noexcept [[nodiscard]] ipv6hdr XskPacket::getIPv6Header() const noexcept { ipv6hdr ipv6Header{}; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) assert(frameLength >= (sizeof(ethhdr) + sizeof(ipv6Header))); assert(v6); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -582,7 +579,6 @@ void XskPacket::setIPv4Header(const iphdr& ipv4Header) noexcept void XskPacket::setIPv6Header(const ipv6hdr& ipv6Header) noexcept { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) assert(frameLength >= (sizeof(ethhdr) + sizeof(ipv6Header))); assert(v6); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -592,7 +588,6 @@ void XskPacket::setIPv6Header(const ipv6hdr& ipv6Header) noexcept [[nodiscard]] udphdr XskPacket::getUDPHeader() const noexcept { udphdr udpHeader{}; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) assert(frameLength >= (sizeof(ethhdr) + (v6 ? sizeof(ipv6hdr) : sizeof(iphdr)) + sizeof(udpHeader))); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) memcpy(&udpHeader, frame + getL4HeaderOffset(), sizeof(udpHeader)); @@ -784,19 +779,13 @@ PacketBuffer XskPacket::clonePacketBuffer() const { const auto size = getDataSize(); PacketBuffer tmp(size); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - memcpy(tmp.data(), frame + getDataOffset(), size); + if (size > 0) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + memcpy(tmp.data(), frame + getDataOffset(), size); + } return tmp; } -void XskPacket::cloneIntoPacketBuffer(PacketBuffer& buffer) const -{ - const auto size = getDataSize(); - buffer.resize(size); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - memcpy(buffer.data(), frame + getDataOffset(), size); -} - bool XskPacket::setPayload(const PacketBuffer& buf) { const auto bufSize = buf.size(); @@ -1094,7 +1083,7 @@ void XskPacket::setHeader(PacketBuffer& buf) } } -PacketBuffer XskPacket::cloneHeadertoPacketBuffer() const +PacketBuffer XskPacket::cloneHeaderToPacketBuffer() const { const auto size = getFrameLen() - getDataSize(); PacketBuffer tmp(size); diff --git a/pdns/xsk.hh b/pdns/xsk.hh index 3b16717989..53b884155a 100644 --- a/pdns/xsk.hh +++ b/pdns/xsk.hh @@ -21,6 +21,7 @@ */ #pragma once +#include "config.h" #ifdef HAVE_XSK #include @@ -54,9 +55,9 @@ class XskPacket; class XskWorker; class XskSocket; +#ifdef HAVE_XSK using MACAddr = std::array; -#ifdef HAVE_XSK using XskPacketPtr = std::unique_ptr; // We use an XskSocket to manage an AF_XDP Socket corresponding to a NIC queue. @@ -251,8 +252,7 @@ public: [[nodiscard]] uint32_t getDataLen() const noexcept; [[nodiscard]] uint32_t getFrameLen() const noexcept; [[nodiscard]] PacketBuffer clonePacketBuffer() const; - void cloneIntoPacketBuffer(PacketBuffer& buffer) const; - [[nodiscard]] PacketBuffer cloneHeadertoPacketBuffer() const; + [[nodiscard]] PacketBuffer cloneHeaderToPacketBuffer() const; void setAddr(const ComboAddress& from_, MACAddr fromMAC, const ComboAddress& to_, MACAddr toMAC) noexcept; bool setPayload(const PacketBuffer& buf); void rewrite() noexcept;