Date: 26 Apr 2000 15:25:23 +1000 From: john@nlc.net.au To: FreeBSD-gnats-submit@freebsd.org Subject: bin/18221: DNS resolver can fail for large DNS responses Message-ID: <20000426052523.85416.qmail@grunt.nlc.net.au>
next in thread | raw e-mail | index | archive | help
>Number: 18221
>Category: bin
>Synopsis: DNS resolver can fail for large DNS responses
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Apr 25 22:30:02 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: John Saunders
>Release: FreeBSD 3.4-STABLE i386
>Organization:
NORTHLINK COMMUNICATIONS
>Environment:
FreeBSD-3.4 (STABLE). However also applies to 4.0-STABLE and
possibly -current.
>Description:
The file /usr/src/lib/libc/net/gethostbydns.c can fail to
resolve a name if the DNS response is very large. A small
patch was made a little while ago to prevent a buffer overrun
from occuring, however this patch prevents all DNS responses.
The following patch causes a partial result to be returned
that is limited to the size of the static buffer. This is
preferable to the current situation of not returning anything.
>How-To-Repeat:
Do an nslookup on any DNS name that has enough results to
overflow a 1024 byte buffer.
>Fix:
--- lib/libc/net/gethostbydns.c.orig Sat Feb 26 11:55:47 2000
+++ lib/libc/net/gethostbydns.c Wed Mar 1 15:03:57 2000
@@ -142,12 +142,7 @@
} while (0)
#define BOUNDS_CHECK(ptr, count) \
- do { \
- if ((ptr) + (count) > eom) { \
- h_errno = NO_RECOVERY; \
- return (NULL); \
- } \
- } while (0)
+ ((ptr) + (count) > eom)
static struct hostent *
gethostanswer(answer, anslen, qname, qtype)
@@ -170,7 +165,7 @@
tname = qname;
host.h_name = NULL;
- eom = answer->buf + anslen;
+ eom = answer->buf + (anslen > MAXPACKET ? MAXPACKET : anslen);
switch (qtype) {
case T_A:
case T_AAAA:
@@ -235,7 +230,11 @@
continue;
}
cp += n; /* name */
- BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ if (BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ))
+ {
+ had_error++;
+ continue;
+ }
type = _getshort(cp);
cp += INT16SZ; /* type */
class = _getshort(cp);
@@ -245,7 +244,11 @@
cp += INT32SZ; /* TTL */
n = _getshort(cp);
cp += INT16SZ; /* len */
- BOUNDS_CHECK(cp, n);
+ if (BOUNDS_CHECK(cp, n))
+ {
+ had_error++;
+ continue;
+ }
erdata = cp + n;
if (class != C_IN) {
/* XXX - debug? syslog? */
@@ -666,7 +669,6 @@
}
if (n > sizeof buf.buf) {
dprintf("static buffer is too small (%d)\n", n);
- return (NULL);
}
if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
return (NULL); /* h_errno was set by gethostanswer() */
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000426052523.85416.qmail>
