It seems I should have been in a bit less of a rush and dug a bit
deeper into this problem.

BIND-9.1.0 is not entirely to blame for the crash it suffers on some
systems when probed in some circumstances by nmap.

I wish to thank ISC and especially Andreas Gustafsson for their quick
response to my somewhat rash and hurried and public report.  My kernel
is not the latest (and not a release version either) and is partly to
blame because it created the rather rare (and if I understand correctly,
undocumented) scenario to which named is left to deal with.  I even
remember reading about the fix being applied to NetBSD recently.  Of
course my NetBSD kernel isn't the only one to suffer this bug, and thus
the value of this work-around, and the lesson to be learned about
defensive coding!  :-)

The following is quoted with permission.

------- start of forwarded message (RFC 934 encapsulation) -------
Message-Id: <[EMAIL PROTECTED]>
Date: Wed,  7 Feb 2001 14:26:41 -0800 (PST)
From: (Andreas Gustafsson) via RT <[EMAIL PROTECTED]>
Reply-To: (Andreas Gustafsson) via RT <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Subject: [ISC-Bugs #811] (bind9) yes, it seems NMAP can trivially crash BIND-9.1.0, at 
least on i386....

> Hmmm...  I tried that little 'nmap -O -sT proven' trick, i.e. against my
> development machine on which I run BIND-9.1.0, and what do you know but
> named drops out almost immediately with a SIGBUS:
>
> Feb  6 13:28:19 proven /netbsd: named: pid 14653 [eid 32771:40, rid 32771:40] sent 
>signal 6: was set-id, core dump not permitted [in /etc/namedb]

This is apparently caused by a kernel bug: A very short-lived incoming
TCP connection can cause accept() to return successfully but fail to
fill in the peer address structure pointed to by the second argument.

The following workaround will be in BIND 9.1.1.
- --
Andreas Gustafsson, [EMAIL PROTECTED]

Index: socket.c
===================================================================
RCS file: /proj/cvs/isc/bind9/lib/isc/unix/socket.c,v
retrieving revision 1.178.2.3
retrieving revision 1.178.2.4
diff -u -r1.178.2.3 -r1.178.2.4
- --- socket.c  2001/02/06 18:10:28     1.178.2.3
+++ socket.c    2001/02/07 20:21:46     1.178.2.4
@@ -1652,40 +1652,40 @@
         * again.
         */
        addrlen = sizeof dev->newsocket->address.type;
+       memset(&dev->newsocket->address.type.sa, 0, addrlen);
        fd = accept(sock->fd, &dev->newsocket->address.type.sa,
                    (void *)&addrlen);
        if (fd < 0) {
- -             if (SOFT_ERROR(errno)) {
+               if (! SOFT_ERROR(errno)) {
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "internal_accept: accept() %s: %s",
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strerror(errno));
+               }
+               select_poke(sock->manager, sock->fd);
+               UNLOCK(&sock->lock);
+               return;
+       } else {
+               if (dev->newsocket->address.type.sa.sa_family != sock->pf) {
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "internal_accept(): "
+                                        "accept() returned peer address "
+                                        "family %u (expected %u)",
+                                        dev->newsocket->address.
+                                        type.sa.sa_family,
+                                        sock->pf);
+                       (void)close(fd);
                        select_poke(sock->manager, sock->fd);
                        UNLOCK(&sock->lock);
                        return;
                }
- -
- -             /*
- -              * If some other error, ignore it as well and hope
- -              * for the best, but log it.
- -              */
- -             if (isc_log_wouldlog(isc_lctx, TRACE_LEVEL))
- -                     socket_log(sock, NULL, TRACE, isc_msgcat,
- -                                ISC_MSGSET_SOCKET,
- -                                ISC_MSG_ACCEPTRETURNED,
- -                                "accept() returned %d/%s",
- -                                errno, strerror(errno));
- -
- -             fd = -1;
- -
- -             UNEXPECTED_ERROR(__FILE__, __LINE__,
- -                              "internal_accept: accept() %s: %s",
- -                              isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
- -                                             ISC_MSG_FAILED, "failed"),
- -                              strerror(errno));
- -
- -             result = ISC_R_UNEXPECTED;
- -     } else {
- -             INSIST(dev->newsocket->address.type.sa.sa_family == sock->pf);
- -             dev->newsocket->address.length = addrlen;
- -             dev->newsocket->pf = sock->pf;
        }
+
+       dev->newsocket->address.length = addrlen;
+       dev->newsocket->pf = sock->pf;

        /*
         * Pull off the done event.

- -------------------------------------------- Managed by Request Tracker

------- end -------

--
                                                        Greg A. Woods

+1 416 218-0098      VE3TCP      <[EMAIL PROTECTED]>      <robohack!woods>
Planix, Inc. <[EMAIL PROTECTED]>; Secrets of the Weird <[EMAIL PROTECTED]>

Reply via email to