This patch fixes several buffer overflows in ISC's BIND 4.9.

Apply by doing:
       cd /usr/src
       patch -p0 < 038_named.patch

And rebuild named by doing:
       cd usr.sbin/named
       make obj
       make depend
       make
       make install

Index: usr.sbin/named/Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/named/Makefile,v
retrieving revision 1.10
diff -u -r1.10 Makefile
--- usr.sbin/named/Makefile     2000/03/29 20:32:55     1.10
+++ usr.sbin/named/Makefile     2001/01/30 02:36:35
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.10 2000/03/29 20:32:55 deraadt Exp $
+#      $OpenBSD: Makefile,v 1.10.4.1 2001/01/30 00:06:40 jason Exp $

SUBDIR= named named-xfer ndc reload restart dig nslookup \
       host dnsquery
@@ -6,6 +6,6 @@
SUBDIR+= doc/bog
.endif

-VER= 4.9.7-REL
+VER= 4.9.8-REL

.include <bsd.subdir.mk>
Index: usr.sbin/named/libresolv/res_comp.c
===================================================================
RCS file: /cvs/src/usr.sbin/named/libresolv/res_comp.c,v
retrieving revision 1.3
diff -u -r1.3 res_comp.c
--- usr.sbin/named/libresolv/res_comp.c 1998/05/22 07:09:08     1.3
+++ usr.sbin/named/libresolv/res_comp.c 2001/01/30 02:36:35
@@ -1,4 +1,4 @@
-/*     $OpenBSD: res_comp.c,v 1.3 1998/05/22 07:09:08 millert Exp $    */
+/*     $OpenBSD: res_comp.c,v 1.3.10.1 2001/01/30 00:06:01 jason Exp $ */

/*
 * ++Copyright++ 1985, 1993
@@ -60,7 +60,7 @@
static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
static char rcsid[] = "$From: res_comp.c,v 8.14 1998/05/11 04:19:47 vixie Exp $";
#else
-static char rcsid[] = "$OpenBSD: res_comp.c,v 1.3 1998/05/22 07:09:08 millert Exp $";
+static char rcsid[] = "$OpenBSD: res_comp.c,v 1.3.10.1 2001/01/30 00:06:01 jason Exp $";
#endif
#endif /* LIBC_SCCS and not lint */

@@ -801,6 +801,25 @@
       if (ns_name_pton(src, tmp, sizeof tmp) == -1)
               return (-1);
       return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*
+ * Reset dnptrs so that there are no active references to pointers at or
+ * after src.
+ */
+void
+ns_name_rollback(src, dnptrs, lastdnptr)
+       const u_char *src;
+       const u_char **dnptrs;
+       const u_char **lastdnptr;
+{
+       while (dnptrs < lastdnptr && *dnptrs != NULL) {
+               if (*dnptrs >= src) {
+                       *dnptrs = NULL;
+                       break;
+               }
+               dnptrs++;
+       }
}

/*
Index: usr.sbin/named/named/ns_forw.c
===================================================================
RCS file: /cvs/src/usr.sbin/named/named/ns_forw.c,v
retrieving revision 1.4
diff -u -r1.4 ns_forw.c
--- usr.sbin/named/named/ns_forw.c      1998/05/22 00:47:38     1.4
+++ usr.sbin/named/named/ns_forw.c      2001/01/30 02:36:41
@@ -1,11 +1,11 @@
-/*     $OpenBSD: ns_forw.c,v 1.4 1998/05/22 00:47:38 millert Exp $     */
+/*     $OpenBSD: ns_forw.c,v 1.4.10.1 2001/01/30 00:06:02 jason Exp $  */

#if !defined(lint) && !defined(SABER)
#if 0
static char sccsid[] = "@(#)ns_forw.c  4.32 (Berkeley) 3/3/91";
static char rcsid[] = "$From: ns_forw.c,v 8.19 1996/12/02 09:27:36 vixie Exp $";
#else
-static char rcsid[] = "$OpenBSD: ns_forw.c,v 1.4 1998/05/22 00:47:38 millert Exp $";
+static char rcsid[] = "$OpenBSD: ns_forw.c,v 1.4.10.1 2001/01/30 00:06:02 jason Exp $";
#endif
#endif /* not lint */

@@ -291,17 +291,23 @@
 *     dname and a_rr are the problematic other name server.
 */
static void
-nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
-       const char *sysloginfo, *queryname, *complaint, *dname;
+nslookupComplain(sysloginfo, net_queryname, complaint, net_dname, a_rr, nsdp)
+       const char *sysloginfo, *net_queryname, *complaint, *net_dname;
       const struct databuf *a_rr, *nsdp;
{
+       char queryname[64], dname[64];
#ifdef STATS
       char nsbuf[20];
       char abuf[20];
#endif
-       char *a, *ns;
+       const char *a, *ns;
       const char *a_type;
       int print_a;
+
+       strncpy(queryname, net_queryname, (sizeof queryname) - 1);
+       queryname[(sizeof queryname) - 1] = '\0';
+       strncpy(dname, net_dname, (sizeof dname) - 1);
+       dname[(sizeof dname) - 1] = '\0';

       dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint));
       if (sysloginfo && queryname && !haveComplained(queryname, complaint))
Index: usr.sbin/named/named/ns_req.c
===================================================================
RCS file: /cvs/src/usr.sbin/named/named/ns_req.c,v
retrieving revision 1.6
diff -u -r1.6 ns_req.c
--- usr.sbin/named/named/ns_req.c       1998/05/22 07:09:18     1.6
+++ usr.sbin/named/named/ns_req.c       2001/01/30 02:36:47
@@ -1,11 +1,11 @@
-/*     $OpenBSD: ns_req.c,v 1.6 1998/05/22 07:09:18 millert Exp $      */
+/*     $OpenBSD: ns_req.c,v 1.6.10.1 2001/01/30 00:06:03 jason Exp $   */

#if !defined(lint) && !defined(SABER)
#if 0
static char sccsid[] = "@(#)ns_req.c   4.47 (Berkeley) 7/1/91";
static char rcsid[] = "$From: ns_req.c,v 8.30 1998/05/11 04:19:45 vixie Exp $";
#else
-static char rcsid[] = "$OpenBSD: ns_req.c,v 1.6 1998/05/22 07:09:18 millert Exp $";
+static char rcsid[] = "$OpenBSD: ns_req.c,v 1.6.10.1 2001/01/30 00:06:03 jason Exp $";
#endif
#endif /* not lint */

@@ -243,6 +243,14 @@
       hp->qr = 1;             /* set Response flag */
       hp->ra = (NoRecurse == 0);

+       if (hp->rcode == FORMERR) {
+               hp->qdcount = htons(0);
+               hp->ancount = htons(0);
+               hp->nscount = htons(0);
+               hp->arcount = htons(0);
+               cp = msg + HFIXEDSZ;
+       }
+
       n = doaddinfo(hp, cp, buflen);
       cp += n;
       buflen -= n;
@@ -1012,12 +1020,12 @@
       GETSHORT(class, *cpp);
       *cpp += INT32SZ;        /* ttl */
       GETSHORT(dlen, *cpp);
-       *cpp += dlen;
-       if (*cpp != eom) {
+       if (*cpp + dlen != eom) {
               dprintf(1, (ddt, "FORMERR IQuery message length off\n"));
               hp->rcode = FORMERR;
               return (Finish);
       }
+       *cpp += dlen;

       /*
        * not all inverse queries are handled.
@@ -1223,6 +1231,25 @@
}

/*
+ * Reset dnptrs so that there are no active references to pointers at or
+ * after src.
+ */
+static void
+ns_name_rollback(src, dnptrs, lastdnptr)
+       const u_char *src;
+       const u_char **dnptrs;
+       const u_char **lastdnptr;
+{
+       while (dnptrs < lastdnptr && *dnptrs != NULL) {
+               if (*dnptrs >= src) {
+                       *dnptrs = NULL;
+                       break;
+               }
+               dnptrs++;
+       }
+}
+
+/*
 * Copy databuf into a resource record for replies.
 * Return size of RR if OK, -1 if buffer is full.
 */
@@ -1294,11 +1321,11 @@
       }
#endif
       if ((n = dn_comp(name, buf, buflen, dnptrs, edp)) < 0)
-               return (-1);
+               goto cleanup;
       cp = buf + n;
       buflen -= n;
       if (buflen < 0)
-               return (-1);
+               goto cleanup;
       PUTSHORT((u_int16_t)type, cp);
       PUTSHORT((u_int16_t)dp->d_class, cp);
       PUTLONG(ttl, cp);
@@ -1311,7 +1338,7 @@
       case T_PTR:
               n = dn_comp((char *)dp->d_data, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               PUTSHORT((u_int16_t)n, sp);
               cp += n;
               break;
@@ -1321,7 +1348,7 @@
               /* Store domain name in answer */
               n = dn_comp((char *)dp->d_data, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               PUTSHORT((u_int16_t)n, sp);
               cp += n;
               if (doadd)
@@ -1335,15 +1362,15 @@
               cp1 = dp->d_data;
               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;
               buflen -= type == T_SOA ? n + 5 * INT32SZ : n;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               cp1 += strlen((char *)cp1) + 1;
               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;
               if (type == T_SOA) {
                       cp1 += strlen((char *)cp1) + 1;
@@ -1361,7 +1388,7 @@
               /* copy order */
               buflen -= INT16SZ;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               bcopy(cp1, cp, INT16SZ);
               cp += INT16SZ;
               cp1 += INT16SZ;
@@ -1371,7 +1398,7 @@
               /* copy preference */
               buflen -= INT16SZ;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               bcopy(cp1, cp, INT16SZ);
               cp += INT16SZ;
               cp1 += INT16SZ;
@@ -1382,7 +1409,7 @@
               n = *cp1++;
               buflen -= n + 1;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               dprintf(1, (ddt, "size of n at flags = %d\n", n));
               *cp++ = n;
               bcopy(cp1,cp,n);
@@ -1395,7 +1422,7 @@
               n = *cp1++;
               buflen -= n + 1;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               *cp++ = n;
               bcopy(cp1,cp,n);
               cp += n;
@@ -1407,7 +1434,7 @@
               n = *cp1++;
               buflen -= n + 1;
               if (buflen < 0)
-                       return (-1);
+                       goto cleanup;
               *cp++ = n;
               bcopy(cp1,cp,n);
               cp += n;
@@ -1420,7 +1447,7 @@
               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               dprintf(1, (ddt, "dn_comp's n = %u\n", n));
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;

               /* save data length */
@@ -1438,7 +1465,7 @@
               cp1 = dp->d_data;

               if ((buflen -= INT16SZ) < 0)
-                       return (-1);
+                       goto cleanup;

               /* copy preference */
               bcopy(cp1, cp, INT16SZ);
@@ -1448,7 +1475,7 @@
               if (type == T_SRV) {
                       buflen -= INT16SZ*2;
                       if (buflen < 0)
-                               return (-1);
+                               goto cleanup;
                       bcopy(cp1, cp, INT16SZ*2);
                       cp += INT16SZ*2;
                       cp1 += INT16SZ*2;
@@ -1456,7 +1483,7 @@

               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;

               /* save data length */
@@ -1470,7 +1497,7 @@
               cp1 = dp->d_data;

               if ((buflen -= INT16SZ) < 0)
-                       return (-1);
+                       goto cleanup;

               /* copy preference */
               bcopy(cp1, cp, INT16SZ);
@@ -1479,13 +1506,13 @@

               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;
               buflen -= n;
               cp1 += strlen((char *)cp1) + 1;
               n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;

               /* save data length */
@@ -1500,7 +1527,7 @@
               /* first just copy over the type_covered, algorithm, */
               /* labels, orig ttl, two timestamps, and the footprint */
               if ((dp->d_size - 18) > buflen)
-                       return (-1);  /* out of room! */
+                       goto cleanup;
               bcopy( cp1, cp, 18 );
               cp  += 18;
               cp1 += 18;
@@ -1509,7 +1536,7 @@
               /* then the signer's name */
               n = dn_comp((char *)cp1, cp, buflen, NULL, NULL);
               if (n < 0)
-                       return (-1);
+                       goto cleanup;
               cp += n;
               buflen -= n;
               cp1 += strlen((char*)cp1)+1;
@@ -1517,7 +1544,7 @@
               /* finally, we copy over the variable-length signature */
               n = dp->d_size - (u_int16_t)((cp1 - dp->d_data));
               if (n > buflen)
-                       return (-1);  /* out of room! */
+                       goto cleanup;
               bcopy(cp1, cp, n);
               cp += n;

@@ -1528,12 +1555,19 @@

       default:
               if (dp->d_size > buflen)
-                       return (-1);
+                       goto cleanup;
               bcopy(dp->d_data, cp, dp->d_size);
               PUTSHORT((u_int16_t)dp->d_size, sp);
               cp += dp->d_size;
       }
       return (cp - buf);
+
+ cleanup:
+       /* Rollback RR. */
+       ns_name_rollback(buf, (const u_char **)dnptrs,
+                        (const u_char **)(dnptrs +
+                                          sizeof dnptrs / sizeof dnptrs[0]));
+       return (-1);
}

#if defined(__STDC__) || defined(__GNUC__)
@@ -1649,6 +1683,11 @@
                               dprintf(5, (ddt,
                                           "addinfo: not enough room, remaining msglen = %d\n",
                                           save_msglen));
+                               /* Rollback RRset. */
+                               ns_name_rollback(save_cp,
+                                                (const u_char **)dnptrs,
+                                                (const u_char **)(dnptrs +
+                                          sizeof dnptrs / sizeof dnptrs[0]));
                               cp = save_cp;
                               msglen = save_msglen;
                               count = save_count;