]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a fuzzing target for the XSK code
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 29 Jan 2024 10:12:27 +0000 (11:12 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 29 Jan 2024 10:12:27 +0000 (11:12 +0100)
fuzzing/corpus/raw-xsk-frames/v4-udp.raw [new file with mode: 0644]
pdns/dnsdist.cc
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/fuzz_xsk.cc [new file with mode: 0644]
pdns/xsk.cc
pdns/xsk.hh

diff --git a/fuzzing/corpus/raw-xsk-frames/v4-udp.raw b/fuzzing/corpus/raw-xsk-frames/v4-udp.raw
new file mode 100644 (file)
index 0000000..31084b5
Binary files /dev/null and b/fuzzing/corpus/raw-xsk-frames/v4-udp.raw differ
index c78fb5a650c439e38971b2eefc0acb9da801c74e..d83066e954b8c86b48621f49726be12bb1507d92 100644 (file)
@@ -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;
index 1a1e3080c1c3b32f82958098449c6e02197679d7..60e76e0ff81e3a387b2b17577e004a39b245f1ea 100644 (file)
@@ -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 (file)
index 0000000..4c67cf4
--- /dev/null
@@ -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<uint8_t*>(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;
+}
index ee05b3a37a6c64f81455dc67a68b1c104e43e95e..d0cb88513a7849b38652712c7099a7e1a0c3fdd6 100644 (file)
@@ -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<int>(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);
index 3b16717989f9c4f36897cb58663f89345219ece9..53b884155a97e387d7b2cbad54b3fb8705c061b8 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #pragma once
+#include "config.h"
 
 #ifdef HAVE_XSK
 #include <array>
@@ -54,9 +55,9 @@ class XskPacket;
 class XskWorker;
 class XskSocket;
 
+#ifdef HAVE_XSK
 using MACAddr = std::array<uint8_t, 6>;
 
-#ifdef HAVE_XSK
 using XskPacketPtr = std::unique_ptr<XskPacket>;
 
 // 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;