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.
This commit is contained in:
Simon Kelley
2017-09-25 20:11:58 +01:00
parent 33e3f1029c
commit 897c113fda
2 changed files with 23 additions and 1 deletions

View File

@@ -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,

View File

@@ -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
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
/* 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
/* 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);