]> granicus.if.org Git - pdns/commitdiff
Throw if DNSName would overflow when asked to read type/class
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 11 Apr 2016 09:14:41 +0000 (11:14 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 11 Apr 2016 09:14:41 +0000 (11:14 +0200)
Otherwise, the caller has to check the consumed size to know
if the type and class he asked for have been read, while it
clearly expected them to be present.
Fix a crash in dnsdist ECS parsing found by american fuzzy lop.

pdns/dnscrypt.cc
pdns/dnsdist-ecs.cc
pdns/dnsname.cc

index fd280e93b88838f9ab758bababf8d59ccd27f6ee..636c02498b125edaec948f6cd7e2679dd63fe528 100644 (file)
@@ -180,6 +180,8 @@ void DnsCryptContext::parsePlaintextQuery(const char * packet, uint16_t packetSi
   unsigned int consumed;
   uint16_t qtype, qclass;
   DNSName qname(packet, packetSize, sizeof(dnsheader), false, &qtype, &qclass, &consumed);
+  if ((packetSize - sizeof(dnsheader)) < (consumed + sizeof(qtype) + sizeof(qclass)))
+    return;
 
   if (qtype != QType::TXT || qclass != QClass::IN)
     return;
index 0bc87ae85ada0c09be59da39844d2f3f60ed4a3c..8f29ade2c67a6c8ecb1ece4660210b81771f703a 100644 (file)
@@ -197,6 +197,9 @@ static int getEDNSOptionsStart(char* packet, const size_t offset, const size_t l
   unsigned int consumed;
   DNSName aname(packet, len, pos, true, &qtype, &qclass, &consumed);
 
+  if ((len - pos) < (consumed + DNS_TYPE_SIZE + DNS_CLASS_SIZE))
+    return ENOENT;
+
   pos += consumed + DNS_TYPE_SIZE + DNS_CLASS_SIZE;
   if(qtype != QType::OPT || (len - pos) < (DNS_TTL_SIZE + DNS_RDLENGTH_SIZE))
     return ENOENT;
index de30cf67feeb22f4ca3007738229bab4dc3a343b..55849c5a9177885b473c4c65c10805c747915d28 100644 (file)
@@ -111,13 +111,19 @@ void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompres
     d_storage.append(1, (char)0); // we just parsed the root
   if(consumed)
     *consumed = pos - opos - offset;
-  if(qtype && pos + labellen + 2 <= end)
+  if(qtype) {
+    if (pos + labellen + 2 > end) {
+      throw std::range_error("Trying to read qtype past the end of the buffer ("+std::to_string((pos - opos) + labellen + 2)+ " > "+std::to_string(len)+")");
+    }
     *qtype=(*(const unsigned char*)pos)*256 + *((const unsigned char*)pos+1);
-
+  }
   pos+=2;
-  if(qclass && pos + labellen + 2 <= end)
+  if(qclass) {
+    if (pos + labellen + 2 > end) {
+      throw std::range_error("Trying to read qclass past the end of the buffer ("+std::to_string((pos - opos) + labellen + 2)+ " > "+std::to_string(len)+")");
+    }
     *qclass=(*(const unsigned char*)pos)*256 + *((const unsigned char*)pos+1);
-
+  }
 }
 
 std::string DNSName::toString(const std::string& separator, const bool trailing) const