Check for bad packets in getaddrinfo.c's getanswer.
The near duplicate in gethnamaddr.c was already doing so (this fix
is basically copy and pasted from there, but with both copies modified
to avoid skirting undefined behavior).
Bug: http://b/32322088
Test: browser still works
Change-Id: Ied6662be567fb1bddc7ceb138cae1da77fb57976
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index 13000f7..54b4618 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -1290,6 +1290,17 @@
static const char AskedForGot[] =
"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+#define BOUNDED_INCR(x) \
+ do { \
+ BOUNDS_CHECK(cp, x); \
+ cp += (x); \
+ } while (/*CONSTCOND*/0)
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if (eom - (ptr) < (count)) { h_errno = NO_RECOVERY; return NULL; } \
+ } while (/*CONSTCOND*/0)
+
static struct addrinfo *
getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
const struct addrinfo *pai)
@@ -1335,7 +1346,8 @@
qdcount = ntohs(hp->qdcount);
bp = hostbuf;
ep = hostbuf + sizeof hostbuf;
- cp = answer->buf + HFIXEDSZ;
+ cp = answer->buf;
+ BOUNDED_INCR(HFIXEDSZ);
if (qdcount != 1) {
h_errno = NO_RECOVERY;
return (NULL);
@@ -1345,7 +1357,7 @@
h_errno = NO_RECOVERY;
return (NULL);
}
- cp += n + QFIXEDSZ;
+ BOUNDED_INCR(n + QFIXEDSZ);
if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
/* res_send() has already verified that the query name is the
* same as the one we sent; this just gets the expanded name
@@ -1370,12 +1382,14 @@
continue;
}
cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
type = _getshort(cp);
cp += INT16SZ; /* type */
class = _getshort(cp);
cp += INT16SZ + INT32SZ; /* class, TTL */
n = _getshort(cp);
cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
if (class != C_IN) {
/* XXX - debug? syslog? */
cp += n;