Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Mar 2000 15:32:15 +1100
From:      "John Saunders" <john@nlc.net.au>
To:        "Bill Fenner" <fenner@research.att.com>
Cc:        <freebsd-gnats-submit@freebsd.org>, "FreeBSD stable" <freebsd-stable@FreeBSD.ORG>
Subject:   Re: bin/10344
Message-ID:  <01a201bf8337$245603c0$4ab511cb@scitec.com.au>
References:  <200002162354.PAA00567@windsor.research.att.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_019F_01BF8393.52335430
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

> I disagree -- bind 8.2.2p5's res_nsend() returns resplen, which is the
> non-adjusted length of the reply that was read from the server.

I've done a complete analysis on the problem, what we have is a simple
case of running off the end of the buffer.

The function gethostanswer is passed a querybuf which has a size of
1024 bytes (determined by the #define MAXPACKET), a DNS answer length
(which in the test case is 7460), and 2 other paramters which don't
concern the problem at hand.

The function then constructs a pointer 'cp' to the starts of the 1024
byte querybuf. It also constructs a pointer 'eom' to indicate the end
of the buffer. Then inside a while statement it extracts each answer.
The while loop terminates if either all answers have been extracted,
or when 'cp' exceeds 'eom', or if an error occured.

The problem is in the construction of the 'eom' pointer, currently
the code uses the DNS answer length to calculate this. However in
the test case the answer is greater than the buffer size. This
allows the while loop to step the 'cp' pointer past the end of the
buffer. The code is...

    eom = answer->buf + anslen;

The corrected code is as follows. It correctly calculates the 'eom'
position for the case of the DNS answer length being longer than
the buffer the answer is provided in.

    eom = answer->buf + (anslen > MAXPACKET ? MAXPACKET : anslen);

Other interesting info. If I redefine MAXPACKET to be 2048 I am able
to get a few more results. If I change it to 4096 then a call to
BOUNDS_CHECK fails and the function returns a NULL. The included
patch alters the way BOUNDS_CHECK works so that the truncated
packet can be handled nicely. I was able to increase some defines
to get more answers back after this change.

I am not sure of the affect on other parts of the system if suddenly
more answers come back. So I would suggest that MAXADDRS and
MAXALIASES remain at 35 and MAXPACKET at 1024.

The patch also removes your "return (NULL)" that you committed, however
I thought that leaving the dprintf in would be a good warning.

Cheers.

--- gethostbydns.c.orig Sat Feb 26 11:55:47 2000
+++ gethostbydns.c Wed Mar  1 15:03:57 2000
@@ -79,8 +79,8 @@

 #define SPRINTF(x) ((size_t)sprintf x)

-#define MAXALIASES 35
-#define MAXADDRS 35
+#define MAXALIASES 300
+#define MAXADDRS 300

 static const char AskedForGot[] =
   "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
@@ -99,7 +99,7 @@
 #if PACKETSZ > 1024
 #define MAXPACKET PACKETSZ
 #else
-#define MAXPACKET 1024
+#define MAXPACKET 8192
 #endif

 typedef union {
@@ -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() */

--            +------------------------------------------------------------+
        .     | John Saunders  - mailto:john@nlc.net.au            (EMail) |
    ,--_|\    |                - http://www.nlc.net.au/              (WWW) |
   /  Oz  \   |                - 02-9489-4932 or 041-822-3814      (Phone) |
   \_,--\_/   | NORTHLINK COMMUNICATIONS P/L - Supplying a professional,   |
         v    | and above all friendly, internet connection service.       |
              +------------------------------------------------------------+


------=_NextPart_000_019F_01BF8393.52335430
Content-Type: application/octet-stream;
	name="gethostbydns.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="gethostbydns.diff"

--- gethostbydns.c.orig	Sat Feb 26 11:55:47 2000=0A=
+++ gethostbydns.c	Wed Mar  1 15:03:57 2000=0A=
@@ -79,8 +79,8 @@=0A=
 =0A=
 #define SPRINTF(x) ((size_t)sprintf x)=0A=
 =0A=
-#define	MAXALIASES	35=0A=
-#define	MAXADDRS	35=0A=
+#define	MAXALIASES	300=0A=
+#define	MAXADDRS	300=0A=
 =0A=
 static const char AskedForGot[] =3D=0A=
 		"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";=0A=
@@ -99,7 +99,7 @@=0A=
 #if PACKETSZ > 1024=0A=
 #define	MAXPACKET	PACKETSZ=0A=
 #else=0A=
-#define	MAXPACKET	1024=0A=
+#define	MAXPACKET	8192=0A=
 #endif=0A=
 =0A=
 typedef union {=0A=
@@ -142,12 +142,7 @@=0A=
 	} while (0)=0A=
 =0A=
 #define BOUNDS_CHECK(ptr, count) \=0A=
-	do { \=0A=
-		if ((ptr) + (count) > eom) { \=0A=
-			h_errno =3D NO_RECOVERY; \=0A=
-			return (NULL); \=0A=
-		} \=0A=
-	} while (0)=0A=
+	((ptr) + (count) > eom)=0A=
 =0A=
 static struct hostent *=0A=
 gethostanswer(answer, anslen, qname, qtype)=0A=
@@ -170,7 +165,7 @@=0A=
 =0A=
 	tname =3D qname;=0A=
 	host.h_name =3D NULL;=0A=
-	eom =3D answer->buf + anslen;=0A=
+	eom =3D answer->buf + (anslen > MAXPACKET ? MAXPACKET : anslen);=0A=
 	switch (qtype) {=0A=
 	case T_A:=0A=
 	case T_AAAA:=0A=
@@ -235,7 +230,11 @@=0A=
 			continue;=0A=
 		}=0A=
 		cp +=3D n;			/* name */=0A=
-		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);=0A=
+		if (BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ))=0A=
+		{=0A=
+			had_error++;=0A=
+			continue;=0A=
+		}=0A=
 		type =3D _getshort(cp);=0A=
  		cp +=3D INT16SZ;			/* type */=0A=
 		class =3D _getshort(cp);=0A=
@@ -245,7 +244,11 @@=0A=
 		cp +=3D INT32SZ;			/* TTL */=0A=
 		n =3D _getshort(cp);=0A=
 		cp +=3D INT16SZ;			/* len */=0A=
-		BOUNDS_CHECK(cp, n);=0A=
+		if (BOUNDS_CHECK(cp, n))=0A=
+		{=0A=
+			had_error++;=0A=
+			continue;=0A=
+		}=0A=
 		erdata =3D cp + n;=0A=
 		if (class !=3D C_IN) {=0A=
 			/* XXX - debug? syslog? */=0A=
@@ -666,7 +669,6 @@=0A=
 	}=0A=
 	if (n > sizeof buf.buf) {=0A=
 		dprintf("static buffer is too small (%d)\n", n);=0A=
-		return (NULL);=0A=
 	}=0A=
 	if (!(hp =3D gethostanswer(&buf, n, qbuf, T_PTR)))=0A=
 		return (NULL);	/* h_errno was set by gethostanswer() */=0A=

------=_NextPart_000_019F_01BF8393.52335430--



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?01a201bf8337$245603c0$4ab511cb>