This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] nss_dns: Skip over non-PTR records in the netent code [BZ #19868]
- From: Florian Weimer <fweimer at redhat dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 25 Mar 2016 20:03:29 +0100
- Subject: [PATCH] nss_dns: Skip over non-PTR records in the netent code [BZ #19868]
- Authentication-results: sourceware.org; auth=none
The DNS packet parser was broken and got de-synchronized by CNAME or
RRSIG records. CNAME records are the larger problem because they come
before the PTR records we are interested in.
Curiously, this meant that the RDATA length check was not actually
missing (it was implied by the loop condition).
Florian
2016-03-25 Florian Weimer <fweimer@redhat.com>
[BZ #19868]
* resolv/nss_dns/dns-network.c (getanswer_r): Skip over non-PTR
records.
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 2eb2f67..8d6ee0d 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -348,10 +348,23 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
if (n < 0 || res_dnok (bp) == 0)
break;
cp += n;
+
+ if (end_of_message - cp < 10)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
+
GETSHORT (type, cp);
GETSHORT (class, cp);
cp += INT32SZ; /* TTL */
- GETSHORT (n, cp);
+ uint16_t rdatalen;
+ GETSHORT (rdatalen, cp);
+ if (end_of_message - cp < rdatalen)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
if (class == C_IN && type == T_PTR)
{
@@ -373,7 +386,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
cp += n;
return NSS_STATUS_UNAVAIL;
}
- cp += n;
+ cp += rdatalen;
if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
{
*alias_pointer++ = bp;
@@ -384,6 +397,9 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
++have_answer;
}
}
+ else
+ /* Skip over unknown record data. */
+ cp += rdatalen;
}
if (have_answer)