nss_dns: Skip over non-PTR records in the netent code [BZ #19868]
Commit Message
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
Comments
On 03/25/2016 08:03 PM, Florian Weimer wrote:
> 2016-03-25 Florian Weimer<fweimer@redhat.com>
>
> [BZ #19868]
> * resolv/nss_dns/dns-network.c (getanswer_r): Skip over non-PTR
> records.
I have pushed this.
Thanks,
Florian
2016-03-25 Florian Weimer <fweimer@redhat.com>
[BZ #19868]
* resolv/nss_dns/dns-network.c (getanswer_r): Skip over non-PTR
records.
@@ -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)