OSDN Git Service

Check for bad packets in getaddrinfo.c's getanswer.
authorElliott Hughes <enh@google.com>
Tue, 15 Nov 2016 20:31:01 +0000 (12:31 -0800)
committerElliott Hughes <enh@google.com>
Tue, 15 Nov 2016 21:00:44 +0000 (13:00 -0800)
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
libc/netbsd/net/getaddrinfo.c

index 5b2f987..c1e6576 100644 (file)
@@ -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; \
                } \
index 937c423..b12f74a 100644 (file)
@@ -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;