diff options
author | Elliott Hughes <enh@google.com> | 2016-12-08 21:22:17 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-12-08 21:22:17 +0000 |
commit | 9eea4e2864ad3684505b087beff21750e13ba43a (patch) | |
tree | 6491216f3a3ce5f36308d0cc73d9676a0e513ee3 | |
parent | c0f1f552f9a4ddba7df737a5ea6696fac6a678ea (diff) | |
parent | 2646bfc213a02323500cbf8e30e3b9f02985cd2b (diff) | |
download | bionic-9eea4e2864ad3684505b087beff21750e13ba43a.tar.gz |
Check for bad packets in getaddrinfo.c's getanswer. am: 87c0dba7b1 am: dc0492ac4f am: f277bb86c6 am: 389e3e92e2 am: 0ffd7a5fb1 am: 0bf10a656b
am: 2646bfc213
Change-Id: I539d424a1176d294e1c1201367f4fe786b345726
-rw-r--r-- | libc/dns/net/getaddrinfo.c | 18 | ||||
-rw-r--r-- | libc/dns/net/gethnamaddr.c | 5 |
2 files changed, 18 insertions, 5 deletions
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c index 829b6791c..fd6c004c1 100644 --- a/libc/dns/net/getaddrinfo.c +++ b/libc/dns/net/getaddrinfo.c @@ -1290,6 +1290,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) @@ -1335,7 +1346,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); @@ -1345,7 +1357,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 @@ -1370,12 +1382,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; diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c index 42f0d0adf..75cb2b3c5 100644 --- a/libc/dns/net/gethnamaddr.c +++ b/libc/dns/net/gethnamaddr.c @@ -186,14 +186,13 @@ debugprintf(const char *msg, res_state res, ...) #define BOUNDED_INCR(x) \ do { \ + BOUNDS_CHECK(cp, x); \ cp += (x); \ - if (cp > eom) \ - goto no_recovery; \ } while (/*CONSTCOND*/0) #define BOUNDS_CHECK(ptr, count) \ do { \ - if ((ptr) + (count) > eom) \ + if (eom - (ptr) < (count)) \ goto no_recovery; \ } while (/*CONSTCOND*/0) |