1338. [bug] libbind: Remote buffer overrun.

This commit is contained in:
Mark Andrews
2002-06-28 06:06:24 +00:00
parent e8fb857c20
commit 020f7361a4
3 changed files with 26 additions and 38 deletions

View File

@@ -1,3 +1,5 @@
1338. [bug] libbind: Remote buffer overrun.
1337. [port] libbind: TrueUNIX 5.1 does not like __align as a
element name.

View File

@@ -52,7 +52,7 @@
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$Id: dns_ho.c,v 1.9 2002/06/28 05:00:55 marka Exp $";
static const char rcsid[] = "$Id: dns_ho.c,v 1.10 2002/06/28 06:06:23 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports. */
@@ -161,7 +161,7 @@ static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
const struct addrinfo *pai);
static void map_v4v6_hostent(struct hostent *hp, char **bp,
int *len);
char *ep);
static void addrsort(res_state, char **, int);
static struct hostent * gethostans(struct irs_ho *this,
const u_char *ansbuf, int anslen,
@@ -1079,7 +1079,7 @@ gethostans(struct irs_ho *this,
struct addrinfo **ret_aip, const struct addrinfo *pai)
{
struct pvt *pvt = (struct pvt *)this->private;
int type, class, buflen, ancount, qdcount, n, haveanswer, had_error;
int type, class, ancount, qdcount, n, haveanswer, had_error;
int error = NETDB_SUCCESS, arcount;
int (*name_ok)(const char *);
const HEADER *hp;
@@ -1088,7 +1088,7 @@ gethostans(struct irs_ho *this,
const u_char *cp;
const char *tname;
const char *hname;
char *bp, **ap, **hap;
char *bp, *ep, **ap, **hap;
char tbuf[MAXDNAME+1];
struct addrinfo sentinel, *cur, ai;
const u_char *arp = NULL;
@@ -1131,13 +1131,13 @@ gethostans(struct irs_ho *this,
qdcount = ntohs(hp->qdcount);
arcount = ntohs(hp->arcount);
bp = pvt->hostbuf;
buflen = sizeof pvt->hostbuf;
ep = pvt->hostbuf + sizeof(pvt->hostbuf);
cp = ansbuf + HFIXEDSZ;
if (qdcount != 1) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
n = dn_expand(ansbuf, eom, cp, bp, buflen);
n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
@@ -1161,7 +1161,6 @@ gethostans(struct irs_ho *this,
pvt->host.h_name = bp;
hname = bp;
bp += n;
buflen -= n;
/* The qname can be abbreviated, but hname is now absolute. */
qname = pvt->host.h_name;
}
@@ -1174,7 +1173,7 @@ gethostans(struct irs_ho *this,
haveanswer = 0;
had_error = 0;
while (ancount-- > 0 && cp < eom && !had_error) {
n = dn_expand(ansbuf, eom, cp, bp, buflen);
n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
had_error++;
continue;
@@ -1207,10 +1206,9 @@ gethostans(struct irs_ho *this,
*ap++ = bp;
n = strlen(bp) + 1; /* for the \0 */
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;
}
@@ -1218,7 +1216,6 @@ gethostans(struct irs_ho *this,
pvt->host.h_name = bp;
hname = bp;
bp += n;
buflen -= n;
continue;
}
if (type == ns_t_dname) {
@@ -1254,7 +1251,7 @@ gethostans(struct irs_ho *this,
cp += n;
n = strlen(t) + 1; /* for the \0 */
if (n > buflen) {
if (n > (ep - bp)) {
had_error++;
continue;
}
@@ -1264,7 +1261,6 @@ gethostans(struct irs_ho *this,
else
hname = bp;
bp += n;
buflen -= n;
continue;
}
@@ -1290,14 +1286,13 @@ gethostans(struct irs_ho *this,
}
/* Get canonical name. */
n = strlen(tbuf) + 1; /* for the \0 */
if (n > buflen) {
if (n > (ep - bp)) {
had_error++;
continue;
}
strcpy(bp, tbuf);
tname = bp;
bp += n;
buflen -= n;
continue;
}
if (qtype == T_ANY) {
@@ -1321,7 +1316,7 @@ gethostans(struct irs_ho *this,
cp += n;
continue;
}
n = dn_expand(ansbuf, eor, cp, bp, buflen);
n = dn_expand(ansbuf, eor, cp, bp, ep - bp);
if (n < 0 || !maybe_hnok(pvt->res, bp) ||
n >= MAXHOSTNAMELEN) {
had_error++;
@@ -1339,7 +1334,6 @@ gethostans(struct irs_ho *this,
if (n != -1) {
n = strlen(bp) + 1; /* for the \0 */
bp += n;
buflen -= n;
}
break;
case ns_t_a6: {
@@ -1439,7 +1433,6 @@ gethostans(struct irs_ho *this,
pvt->host.h_name = bp;
hname = bp;
bp += nn;
buflen -= nn;
}
/* Ensure alignment. */
bp = (char *)(((u_long)bp + (sizeof(align) - 1)) &
@@ -1493,15 +1486,14 @@ gethostans(struct irs_ho *this,
haveanswer);
if (pvt->host.h_name == NULL) {
n = strlen(qname) + 1; /* for the \0 */
if (n > buflen || n >= MAXHOSTNAMELEN)
if (n > (ep - bp) || n >= MAXHOSTNAMELEN)
goto no_recovery;
strcpy(bp, qname);
pvt->host.h_name = bp;
bp += n;
buflen -= n;
}
if (pvt->res->options & RES_USE_INET6)
map_v4v6_hostent(&pvt->host, &bp, &buflen);
map_v4v6_hostent(&pvt->host, &bp, ep);
RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
return (&pvt->host);
} else {
@@ -1575,7 +1567,7 @@ add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai)
}
static void
map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) {
map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {
char **ap;
if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
@@ -1588,17 +1580,15 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) {
if (i != 0)
i = sizeof(align) - i;
if (*lenp < (i + IN6ADDRSZ)) {
if ((ep - *bpp) < (i + IN6ADDRSZ)) {
/* Out of memory. Truncate address list here. */
*ap = NULL;
return;
}
*bpp += i;
*lenp -= i;
map_v4v6_address(*ap, *bpp);
*ap = *bpp;
*bpp += IN6ADDRSZ;
*lenp -= IN6ADDRSZ;
}
}

View File

@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$Id: dns_nw.c,v 1.5 2002/02/27 04:03:11 marka Exp $";
static const char rcsid[] = "$Id: dns_nw.c,v 1.6 2002/06/28 06:06:24 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports. */
@@ -299,8 +299,8 @@ get1101answer(struct irs_nw *this,
int af, const char *name, const u_char *addr, int addrlen)
{
struct pvt *pvt = (struct pvt *)this->private;
int type, class, buflen, ancount, qdcount, haveanswer;
char *bp, **ap;
int type, class, ancount, qdcount, haveanswer;
char *bp, *ep, **ap;
u_char *cp, *eom;
HEADER *hp;
@@ -332,7 +332,7 @@ get1101answer(struct irs_nw *this,
/* Prepare a return structure. */
bp = pvt->buf;
buflen = sizeof pvt->buf;
ep = pvt->buf + sizeof(pvt->buf);
pvt->net.n_name = NULL;
pvt->net.n_aliases = pvt->ali;
pvt->net.n_addrtype = af;
@@ -345,20 +345,19 @@ get1101answer(struct irs_nw *this,
if (name != NULL) {
int n = strlen(name) + 1;
if (n > buflen) {
if (n > (ep - bp)) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
pvt->net.n_name = strcpy(bp, name);
bp += n;
buflen -= n;
}
break;
case by_addr:
if (addr != NULL && addrlen != 0) {
int n = addrlen / 8 + ((addrlen % 8) != 0);
if (INADDRSZ > buflen) {
if (INADDRSZ > (ep - bp)) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
@@ -366,7 +365,6 @@ get1101answer(struct irs_nw *this,
memcpy(bp, addr, n);
pvt->net.n_addr = bp;
bp += INADDRSZ;
buflen -= INADDRSZ;
}
break;
default:
@@ -377,7 +375,7 @@ get1101answer(struct irs_nw *this,
ap = pvt->ali;
haveanswer = 0;
while (--ancount >= 0 && cp < eom) {
int n = dn_expand(ansbuf, eom, cp, bp, buflen);
int n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
cp += n; /* Owner */
if (n < 0 || !maybe_dnok(pvt->res, bp) ||
@@ -392,7 +390,7 @@ get1101answer(struct irs_nw *this,
if (class == C_IN && type == T_PTR) {
int nn;
nn = dn_expand(ansbuf, eom, cp, bp, buflen);
nn = dn_expand(ansbuf, eom, cp, bp, ep - bp);
if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
@@ -408,7 +406,6 @@ get1101answer(struct irs_nw *this,
*ap++ = bp;
nn = strlen(bp) + 1;
bp += nn;
buflen -= nn;
haveanswer++;
break;
}
@@ -419,7 +416,7 @@ get1101answer(struct irs_nw *this,
sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
&b1, &b2, &b3, &b4) != 4)
break;
if (buflen < INADDRSZ) {
if ((ep - bp) < INADDRSZ) {
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
return (NULL);
}
@@ -428,7 +425,6 @@ get1101answer(struct irs_nw *this,
*bp++ = b3;
*bp++ = b2;
*bp++ = b1;
buflen -= INADDRSZ;
pvt->net.n_length = INADDRSZ * 8;
haveanswer++;
}