From 8df35cae5920770f3ca2040b56aa6e1cdc468740 Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 26 Jun 2002 08:18:05 +0000 Subject: Include more robust checking of end of buffer that more completely plugs the hole. --- lib/libc/net/gethostbydns.c | 39 +++++++++++++++------------------------ lib/libc/net/getnetbydns.c | 9 ++++----- lib/libc/net/map_v4v6.c | 8 +++----- lib/libc/net/name6.c | 28 ++++++++++------------------ 4 files changed, 32 insertions(+), 52 deletions(-) diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index e40c141..518585a 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -167,8 +167,8 @@ gethostanswer(answer, anslen, qname, qtype) const u_char *cp; int n; const u_char *eom, *erdata; - char *bp, **ap, **hap; - int type, class, buflen, ancount, qdcount; + char *bp, *ep, **ap, **hap; + int type, class, ancount, qdcount; int haveanswer, had_error; int toobig = 0; char tbuf[MAXDNAME]; @@ -197,14 +197,14 @@ gethostanswer(answer, anslen, qname, qtype) ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - buflen = sizeof hostbuf; + ep = hostbuf + sizeof hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { h_errno = NO_RECOVERY; return (NULL); } - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { h_errno = NO_RECOVERY; return (NULL); @@ -222,7 +222,6 @@ gethostanswer(answer, anslen, qname, qtype) } host.h_name = bp; bp += n; - buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = host.h_name; } @@ -236,7 +235,7 @@ gethostanswer(answer, anslen, qname, qtype) had_error = 0; _dns_ttl_ = -1; while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; @@ -280,17 +279,15 @@ gethostanswer(answer, anslen, qname, qtype) continue; } bp += n; - buflen -= n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { + if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); host.h_name = bp; bp += n; - buflen -= n; continue; } if (qtype == T_PTR && type == T_CNAME) { @@ -306,14 +303,13 @@ gethostanswer(answer, anslen, qname, qtype) } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { + if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; - buflen -= n; continue; } if (type != qtype) { @@ -333,7 +329,7 @@ gethostanswer(answer, anslen, qname, qtype) cp += n; continue; /* XXX - had_error++ ? */ } - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_hnok(bp)) { had_error++; break; @@ -357,7 +353,6 @@ gethostanswer(answer, anslen, qname, qtype) break; } bp += n; - buflen -= n; } break; #else @@ -369,8 +364,7 @@ gethostanswer(answer, anslen, qname, qtype) break; } bp += n; - buflen -= n; - _map_v4v6_hostent(&host, &bp, &buflen); + _map_v4v6_hostent(&host, &bp, &ep); } h_errno = NETDB_SUCCESS; return (&host); @@ -393,13 +387,12 @@ gethostanswer(answer, anslen, qname, qtype) host.h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; - buflen -= nn; } buflen -= sizeof(align) - ((u_long)bp % sizeof(align)); bp += sizeof(align) - ((u_long)bp % sizeof(align)); - if (bp + n >= &hostbuf[sizeof hostbuf]) { + if (bp + n >= ep) { dprintf("size (%d) too big\n", n); had_error++; continue; @@ -413,7 +406,6 @@ gethostanswer(answer, anslen, qname, qtype) } bcopy(cp, *hap++ = bp, n); bp += n; - buflen -= n; cp += n; if (cp != erdata) { h_errno = NO_RECOVERY; @@ -443,15 +435,14 @@ gethostanswer(answer, anslen, qname, qtype) # endif /*RESOLVSORT*/ if (!host.h_name) { n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) + if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); host.h_name = bp; bp += n; - buflen -= n; } if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &buflen); + _map_v4v6_hostent(&host, &bp, &ep); h_errno = NETDB_SUCCESS; return (&host); } @@ -489,7 +480,7 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) int af; querybuf buf; const char *cp; - char *bp; + char *bp, *ep; int n, size, type, len; name = va_arg(ap, const char *); @@ -548,7 +539,7 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; - len = sizeof hostbuf - MAXDNAME; + ep = hostbuf + sizeof hostbuf; host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; @@ -556,7 +547,7 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &len); + _map_v4v6_hostent(&host, &bp, &ep); h_errno = NETDB_SUCCESS; *(struct hostent **)rval = &host; return NS_SUCCESS; diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c index 730d796..324c7cd 100644 --- a/lib/libc/net/getnetbydns.c +++ b/lib/libc/net/getnetbydns.c @@ -115,9 +115,9 @@ getnetanswer(answer, anslen, net_i) u_char *cp; int n; u_char *eom; - int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; + int type, class, ancount, qdcount, haveanswer, i, nchar; char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN]; - char *in, *st, *pauxt, *bp, **ap; + char *in, *st, *pauxt, *bp, *ep, **ap; char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; static struct netent net_entry; static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; @@ -141,7 +141,6 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; ancount = ntohs(hp->ancount); /* #/records in the answer section */ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ bp = netbuf; - buflen = sizeof(netbuf); cp = answer->buf + HFIXEDSZ; if (!qdcount) { if (hp->aa) @@ -157,7 +156,7 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; net_entry.n_aliases = net_aliases; haveanswer = 0; while (--ancount >= 0 && cp < eom) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_dnok(bp)) break; cp += n; @@ -169,7 +168,7 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; cp += INT32SZ; /* TTL */ GETSHORT(n, cp); if (class == C_IN && type == T_PTR) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_hnok(bp)) { cp += n; return (NULL); diff --git a/lib/libc/net/map_v4v6.c b/lib/libc/net/map_v4v6.c index c3bab94..c8aaa3a 100644 --- a/lib/libc/net/map_v4v6.c +++ b/lib/libc/net/map_v4v6.c @@ -99,10 +99,10 @@ _map_v4v6_address(src, dst) } void -_map_v4v6_hostent(hp, bpp, lenp) +_map_v4v6_hostent(hp, bpp, epp) struct hostent *hp; char **bpp; - int *lenp; + char **epp; { char **ap; @@ -113,16 +113,14 @@ _map_v4v6_hostent(hp, bpp, lenp) for (ap = hp->h_addr_list; *ap; ap++) { int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); - if (*lenp < (i + IN6ADDRSZ)) { + if (*epp - *bpp < (i + IN6ADDRSZ)) { /* Out of memory. Truncate address list here. XXX */ *ap = NULL; return; } *bpp += i; - *lenp -= i; _map_v4v6_address(*ap, *bpp); *ap = *bpp; *bpp += IN6ADDRSZ; - *lenp -= IN6ADDRSZ; } } diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c index 51edfd5..83c3caf 100644 --- a/lib/libc/net/name6.c +++ b/lib/libc/net/name6.c @@ -997,8 +997,8 @@ getanswer(answer, anslen, qname, qtype, template, errp) const u_char *cp; int n; const u_char *eom, *erdata; - char *bp, **ap, **hap, *obp; - int type, class, buflen, ancount, qdcount; + char *bp, *ep, **ap, **hap; + int type, class, ancount, qdcount; int haveanswer, had_error; char tbuf[MAXDNAME]; const char *tname; @@ -1063,14 +1063,14 @@ getanswer(answer, anslen, qname, qtype, template, errp) ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - buflen = sizeof hostbuf; + ep = hostbuf + sizeof hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { *errp = NO_RECOVERY; return (NULL); } - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { *errp = NO_RECOVERY; return (NULL); @@ -1088,7 +1088,6 @@ getanswer(answer, anslen, qname, qtype, template, errp) } template->h_name = bp; bp += n; - buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = template->h_name; } @@ -1101,7 +1100,7 @@ getanswer(answer, anslen, qname, qtype, template, errp) haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); DNS_FATAL(n >= 0); DNS_FATAL((*name_ok)(bp)); cp += n; /* name */ @@ -1131,15 +1130,13 @@ getanswer(answer, anslen, qname, qtype, template, errp) n = strlen(bp) + 1; /* for the \0 */ DNS_FATAL(n < MAXHOSTNAMELEN); bp += n; - buflen -= n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - DNS_FATAL(n <= buflen); + DNS_FATAL(n <= ep - bp); DNS_FATAL(n < MAXHOSTNAMELEN); strcpy(bp, tbuf); template->h_name = bp; bp += n; - buflen -= n; continue; } if (qtype == T_PTR && type == T_CNAME) { @@ -1155,21 +1152,20 @@ getanswer(answer, anslen, qname, qtype, template, errp) } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { + if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; - buflen -= n; continue; } DNS_ASSERT(type == qtype); switch (type) { case T_PTR: DNS_ASSERT(strcasecmp(tname, bp) == 0); - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); DNS_FATAL(n >= 0); DNS_FATAL(res_hnok(bp)); #if MULTI_PTRS_ARE_ALIASES @@ -1191,7 +1187,6 @@ getanswer(answer, anslen, qname, qtype, template, errp) break; } bp += n; - buflen -= n; } break; #else @@ -1209,13 +1204,12 @@ getanswer(answer, anslen, qname, qtype, template, errp) template->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; - buflen -= nn; } obp = bp; /* ALIGN rounds up */ bp = (char *)ALIGN(bp); buflen -= (bp - obp); - DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]); + DNS_FATAL(bp + n < ep); DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]); #ifdef FILTER_V4MAPPED if (type == T_AAAA) { @@ -1226,7 +1220,6 @@ getanswer(answer, anslen, qname, qtype, template, errp) #endif bcopy(cp, *hap++ = bp, n); bp += n; - buflen -= n; cp += n; if (cp != erdata) { *errp = NO_RECOVERY; @@ -1244,12 +1237,11 @@ getanswer(answer, anslen, qname, qtype, template, errp) *hap = NULL; if (!template->h_name) { n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) + if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); template->h_name = bp; bp += n; - buflen -= n; } *errp = NETDB_SUCCESS; return (template); -- cgit v1.1