From: Remi Gacogne Date: Mon, 11 Apr 2016 09:14:41 +0000 (+0200) Subject: Throw if DNSName would overflow when asked to read type/class X-Git-Tag: dnsdist-1.0.0-beta1~9^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F3691%2Fhead;p=thirdparty%2Fpdns.git Throw if DNSName would overflow when asked to read type/class 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. --- diff --git a/pdns/dnscrypt.cc b/pdns/dnscrypt.cc index fd280e93b8..636c02498b 100644 --- a/pdns/dnscrypt.cc +++ b/pdns/dnscrypt.cc @@ -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; diff --git a/pdns/dnsdist-ecs.cc b/pdns/dnsdist-ecs.cc index 0bc87ae85a..8f29ade2c6 100644 --- a/pdns/dnsdist-ecs.cc +++ b/pdns/dnsdist-ecs.cc @@ -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; diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index de30cf67fe..55849c5a91 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -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