From 105a0bdfa5e44429e64c31fdbeabc959df8ad87e Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 15 Nov 2016 12:31:01 -0800 Subject: [PATCH] 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). (cherrypick of 27a4459d945e34fabd7166791a5b862ccea83f23 from master.) Bug: http://b/32322088 Change-Id: I9668b1515ad87665e47cae962812474bb480f205 --- libc/netbsd/gethnamaddr.c | 7 ++----- libc/netbsd/net/getaddrinfo.c | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/libc/netbsd/gethnamaddr.c b/libc/netbsd/gethnamaddr.c index 5b2f98750..c1e6576fa 100644 --- a/libc/netbsd/gethnamaddr.c +++ b/libc/netbsd/gethnamaddr.c @@ -158,16 +158,13 @@ dprintf(const char *msg, res_state res, ...) #define BOUNDED_INCR(x) \ do { \ + BOUNDS_CHECK(cp, (x)); \ cp += (x); \ - if (cp > eom) { \ - h_errno = NO_RECOVERY; \ - return NULL; \ - } \ } while (/*CONSTCOND*/0) #define BOUNDS_CHECK(ptr, count) \ do { \ - if ((ptr) + (count) > eom) { \ + if (eom - (ptr) < (count)) { \ h_errno = NO_RECOVERY; \ return NULL; \ } \ diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c index 937c42350..b12f74a06 100644 --- a/libc/netbsd/net/getaddrinfo.c +++ b/libc/netbsd/net/getaddrinfo.c @@ -1292,6 +1292,17 @@ ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 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) @@ -1337,7 +1348,8 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 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); @@ -1347,7 +1359,7 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 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 @@ -1372,12 +1384,14 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 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; -- 2.11.0