From john@nlc.net.au  Tue Apr 25 22:25:35 2000
Return-Path: <john@nlc.net.au>
Received: from nhj.nlc.net.au (nhj.nlc.net.au [203.24.133.1])
	by hub.freebsd.org (Postfix) with SMTP id B970837B765
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 25 Apr 2000 22:25:28 -0700 (PDT)
	(envelope-from john@nlc.net.au)
Received: (qmail 17667 invoked from network); 26 Apr 2000 15:25:26 +1000
Received: from grunt.nlc.net.au (203.24.133.5)
  by nhj.nlc.net.au with SMTP; 26 Apr 2000 15:25:26 +1000
Received: (qmail 85417 invoked by uid 1000); 26 Apr 2000 15:25:24 +1000
Message-Id: <20000426052523.85416.qmail@grunt.nlc.net.au>
Date: 26 Apr 2000 15:25:23 +1000
From: john@nlc.net.au
Reply-To: john@nlc.net.au
To: FreeBSD-gnats-submit@freebsd.org
Subject: DNS resolver can fail for large DNS responses
X-Send-Pr-Version: 3.2

>Number:         18221
>Category:       bin
>Synopsis:       DNS resolver can fail for large DNS responses
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    dougb
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 25 22:30:02 PDT 2000
>Closed-Date:    Sun Mar 4 22:22:41 PST 2001
>Last-Modified:  Sun Mar 04 22:23:20 PST 2001
>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:

From: Bill Fenner <fenner@research.att.com>
To: john@nlc.net.au
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/18221: DNS resolver can fail for large DNS responses
Date: Wed, 26 Apr 2000 08:08:32 -0700

 I didn't return the truncated response because I was worried about
 whether all the relevant functions handled truncated responses.
 Have you checked this?
 
 >@@ -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() */
 
 Didn't you just reintroduce the buffer overrun?  (e.g. you at least want
 to truncate n to sizeof buf.buf)
 
   Bill
 
State-Changed-From-To: open->feedback 
State-Changed-By: dougb 
State-Changed-When: Sat Feb 3 21:26:15 PST 2001 
State-Changed-Why:  

Can you test this problem with an up to date -current or -stable and report 
your findings please? 


Responsible-Changed-From-To: freebsd-bugs->dougb 
Responsible-Changed-By: dougb 
Responsible-Changed-When: Sat Feb 3 21:26:15 PST 2001 
Responsible-Changed-Why:  

I'll handle the feedback. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=18221 
State-Changed-From-To: feedback->closed 
State-Changed-By: dougb 
State-Changed-When: Sun Mar 4 22:22:41 PST 2001 
State-Changed-Why:  

Feedback timeout. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=18221 
>Unformatted:
