Commit 897c113f authored by Simon Kelley's avatar Simon Kelley

Security fix, CVE-2017-14496, Integer underflow in DNS response creation.

Fix DoS in DNS. Invalid boundary checks in the
add_pseudoheader function allows a memcpy call with negative
size An attacker which can send malicious DNS queries
to dnsmasq can trigger a DoS remotely.
dnsmasq is vulnerable only if one of the following option is
specified: --add-mac, --add-cpe-id or --add-subnet.
parent 33e3f102
...@@ -60,6 +60,17 @@ version 2.78 ...@@ -60,6 +60,17 @@ version 2.78
and Kevin Hamacher of the Google Security Team for and Kevin Hamacher of the Google Security Team for
finding this. finding this.
Fix DoS in DNS. Invalid boundary checks in the
add_pseudoheader function allows a memcpy call with negative
size An attacker which can send malicious DNS queries
to dnsmasq can trigger a DoS remotely.
dnsmasq is vulnerable only if one of the following option is
specified: --add-mac, --add-cpe-id or --add-subnet.
CVE-2017-14496 applies.
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
and Kevin Hamacher of the Google Security Team for
finding this.
version 2.77 version 2.77
Generate an error when configured with a CNAME loop, Generate an error when configured with a CNAME loop,
......
...@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l ...@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
GETSHORT(len, p); GETSHORT(len, p);
/* malformed option, delete the whole OPT RR and start again. */ /* malformed option, delete the whole OPT RR and start again. */
if (i + len > rdlen) if (i + 4 + len > rdlen)
{ {
rdlen = 0; rdlen = 0;
is_last = 0; is_last = 0;
...@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l ...@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
header, plen))) header, plen)))
return plen; return plen;
if (p + 11 > limit)
return plen; /* Too big */
*p++ = 0; /* empty name */ *p++ = 0; /* empty name */
PUTSHORT(T_OPT, p); PUTSHORT(T_OPT, p);
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */ PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
...@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l ...@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
/* Copy back any options */ /* Copy back any options */
if (buff) if (buff)
{ {
if (p + rdlen > limit)
{
free(buff);
return plen; /* Too big */
}
memcpy(p, buff, rdlen); memcpy(p, buff, rdlen);
free(buff); free(buff);
p += rdlen; p += rdlen;
...@@ -220,8 +227,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l ...@@ -220,8 +227,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
/* Add new option */ /* Add new option */
if (optno != 0 && replace != 2) if (optno != 0 && replace != 2)
{ {
if (p + 4 > limit)
return plen; /* Too big */
PUTSHORT(optno, p); PUTSHORT(optno, p);
PUTSHORT(optlen, p); PUTSHORT(optlen, p);
if (p + optlen > limit)
return plen; /* Too big */
memcpy(p, opt, optlen); memcpy(p, opt, optlen);
p += optlen; p += optlen;
PUTSHORT(p - datap, lenp); PUTSHORT(p - datap, lenp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment