diff options
author | peter <peter@FreeBSD.org> | 1998-05-02 13:11:02 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-05-02 13:11:02 +0000 |
commit | 119bf1955726447fe80a4419229bf6ca6a606026 (patch) | |
tree | b507d8454b4648373f44ea660cc33052c678a495 /lib/libc/net/res_send.c | |
parent | 52007a8cf8e565a9578ec116b85253372aa5d810 (diff) | |
download | FreeBSD-src-119bf1955726447fe80a4419229bf6ca6a606026.zip FreeBSD-src-119bf1955726447fe80a4419229bf6ca6a606026.tar.gz |
Update libc dns code to 4.9.7-T1B level. This involved chopping out large
chunks of res_comp.c and replacing it with chunks of bind-8.1.1's resolver
code. (There are no interface changes though)
The other parts are better bounds checking related.
Diffstat (limited to 'lib/libc/net/res_send.c')
-rw-r--r-- | lib/libc/net/res_send.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index 70a5c17..b8acbfd 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -55,8 +55,8 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static char orig_rcsid[] = "From: Id: res_send.c,v 8.13 1997/06/01 20:34:37 vixie Exp"; -static char rcsid[] = "$Id: res_send.c,v 1.19 1997/09/14 09:44:34 peter Exp $"; +static char orig_rcsid[] = "From: Id: res_send.c,v 8.14 1998/04/07 04:59:46 vixie Exp $"; +static char rcsid[] = "$Id: res_send.c,v 1.20 1997/09/16 06:03:54 peter Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -191,6 +191,8 @@ res_isourserver(inp) /* int * res_nameinquery(name, type, class, buf, eom) * look for (name,type,class) in the query section of packet (buf,eom) + * requires: + * buf + HFIXESDZ <= eom * returns: * -1 : format error * 0 : not found @@ -215,6 +217,8 @@ res_nameinquery(name, type, class, buf, eom) if (n < 0) return (-1); cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); ttype = _getshort(cp); cp += INT16SZ; tclass = _getshort(cp); cp += INT16SZ; if (ttype == type && @@ -244,6 +248,9 @@ res_queriesmatch(buf1, eom1, buf2, eom2) register const u_char *cp = buf1 + HFIXEDSZ; int qdcount = ntohs(((HEADER*)buf1)->qdcount); + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) return (0); while (qdcount-- > 0) { @@ -254,6 +261,8 @@ res_queriesmatch(buf1, eom1, buf2, eom2) if (n < 0) return (-1); cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); ttype = _getshort(cp); cp += INT16SZ; tclass = _getshort(cp); cp += INT16SZ; if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) @@ -279,6 +288,10 @@ res_send(buf, buflen, ans, anssiz) /* errno should have been set by res_init() in this case. */ return (-1); } + if (anssiz < HFIXEDSZ) { + errno = EINVAL; + return (-1); + } DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), (stdout, ";; res_send()\n"), buf, buflen); v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; @@ -423,6 +436,17 @@ read_len: len = anssiz; } else len = resplen; + if (len < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + terrno = EMSGSIZE; + badns |= (1 << ns); + res_close(); + goto next_ns; + } cp = ans; while (len != 0 && (n = read(s, (char *)cp, (int)len)) > 0) { @@ -590,6 +614,11 @@ read_len: timeout.tv_sec = 1; } wait: + if (s < 0) { + Perror(stderr, "s out-of-bounds", EMFILE); + res_close(); + goto next_ns; + } if (use_poll) { struct sigaction sa, osa; int sigsys_installed = 0; @@ -662,6 +691,18 @@ read_len: goto next_ns; } gotsomewhere = 1; + if (resplen < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; undersized: %d\n", + resplen)); + terrno = EMSGSIZE; + badns |= (1 << ns); + res_close(); + goto next_ns; + } if (hp->id != anhp->id) { /* * response from old query, ignore it. |