forked from pool/glibc
Andreas Schwab
44414488d6
- Import patches from 2.23 branch OBS-URL: https://build.opensuse.org/request/show/394998 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=436
105 lines
2.8 KiB
Diff
105 lines
2.8 KiB
Diff
2016-04-27 Florian Weimer <fweimer@redhat.com>
|
|
|
|
[BZ #19831]
|
|
* resolv/nss_dns/dns-host.c (rrtype_to_rdata_length): New
|
|
function.
|
|
(getanswer_r): Check RDATA length against RRTYPE and QTYPE.
|
|
(gaih_getanswer_slice): Check RDATA length against RRTYPE.
|
|
|
|
Index: glibc-2.23/resolv/nss_dns/dns-host.c
|
|
===================================================================
|
|
--- glibc-2.23.orig/resolv/nss_dns/dns-host.c
|
|
+++ glibc-2.23/resolv/nss_dns/dns-host.c
|
|
@@ -134,6 +134,22 @@ extern enum nss_status _nss_dns_gethostb
|
|
char **canonp);
|
|
hidden_proto (_nss_dns_gethostbyname3_r)
|
|
|
|
+/* Return the expected RDATA length for an address record type (A or
|
|
+ AAAA). */
|
|
+static int
|
|
+rrtype_to_rdata_length (int type)
|
|
+{
|
|
+ switch (type)
|
|
+ {
|
|
+ case T_A:
|
|
+ return INADDRSZ;
|
|
+ case T_AAAA:
|
|
+ return IN6ADDRSZ;
|
|
+ default:
|
|
+ return -1;
|
|
+ }
|
|
+}
|
|
+
|
|
enum nss_status
|
|
_nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
|
char *buffer, size_t buflen, int *errnop,
|
|
@@ -888,6 +904,15 @@ getanswer_r (const querybuf *answer, int
|
|
cp += n;
|
|
continue; /* XXX - had_error++ ? */
|
|
}
|
|
+
|
|
+ /* Stop parsing at a record whose length is incorrect. */
|
|
+ if (n != rrtype_to_rdata_length (type))
|
|
+ {
|
|
+ ++had_error;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Skip records of the wrong type. */
|
|
if (n != result->h_length)
|
|
{
|
|
cp += n;
|
|
@@ -1124,25 +1149,25 @@ gaih_getanswer_slice (const querybuf *an
|
|
}
|
|
continue;
|
|
}
|
|
-#if 1
|
|
- // We should not see any types other than those explicitly listed
|
|
- // below. Some types sent by server seem missing, though. Just
|
|
- // collect the data for now.
|
|
- if (__glibc_unlikely (type != T_A && type != T_AAAA))
|
|
-#else
|
|
- if (__builtin_expect (type == T_SIG, 0)
|
|
- || __builtin_expect (type == T_KEY, 0)
|
|
- || __builtin_expect (type == T_NXT, 0)
|
|
- || __builtin_expect (type == T_PTR, 0)
|
|
- || __builtin_expect (type == T_DNAME, 0))
|
|
-#endif
|
|
+
|
|
+ /* Stop parsing if we encounter a record with incorrect RDATA
|
|
+ length. */
|
|
+ if (type == T_A || type == T_AAAA)
|
|
{
|
|
+ if (n != rrtype_to_rdata_length (type))
|
|
+ {
|
|
+ ++had_error;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Skip unknown records. */
|
|
cp += n;
|
|
continue;
|
|
}
|
|
- if (type != T_A && type != T_AAAA)
|
|
- abort ();
|
|
|
|
+ assert (type == T_A || type == T_AAAA);
|
|
if (*pat == NULL)
|
|
{
|
|
uintptr_t pad = (-(uintptr_t) buffer
|
|
@@ -1176,12 +1201,6 @@ gaih_getanswer_slice (const querybuf *an
|
|
}
|
|
|
|
(*pat)->family = type == T_A ? AF_INET : AF_INET6;
|
|
- if (__builtin_expect ((type == T_A && n != INADDRSZ)
|
|
- || (type == T_AAAA && n != IN6ADDRSZ), 0))
|
|
- {
|
|
- ++had_error;
|
|
- continue;
|
|
- }
|
|
memcpy ((*pat)->addr, cp, n);
|
|
cp += n;
|
|
(*pat)->scopeid = 0;
|