COMMAND

    select(2)/accept(2)

SYSTEMS AFFECTED

    NetBSD, other systems?

PROBLEM

    Following is  based on  NetBSD Security  Advisory.   A problem has
    been identified which  allows remote attackers  to wedge many  TCP
    services running  on 4.4BSD-derived  systems, including  X servers
    and all  services run  from inetd.   Other (non-BSD)  systems  are
    believed to  be affected  as well.   Many TCP  servers open  a TCP
    socket in  the default  blocking mode,  use select(2)  to wait for
    connections,  and  then  accept(2)  connections  in blocking mode.
    Under  some  circumstances,  the  accept(2)  may  hang waiting for
    another connection, denying service  to clients trying to  connect
    to other ports.  The scenario which causes this is:

        * Connection is initiated by client; 3WHS completes,
        * Server process is awakened and select(2) succeeds,
        * Connection  is closed  by client  (e.g. by  sending a  RST).
          Connection is removed from accept(2) queue on server,
        * Server process does an accept(2), which hangs waiting for  a
          connection.

    This scenario is sometimes difficult to reproduce, particularly if
    the server is very fast and the network is relatively slow.  It is
    most effective if the server is slow and/or must do a lot of  work
    between the  select(2) and  accept(2).   The same  bug shows up in
    (for example)  select()+write() if  there's more  than one process
    writing to the same open file.

SOLUTION

    1) Modify all TCP  servers to use non-blocking  listening sockets.
       Unfortunately, this requires changing  a large amount of  code,
       much of it maintained by third parties.

    2) Modify  the kernel  to not  remove sockets  from the  accept(2)
       queue when they are closed.  A change that implements this  has
       been added to NetBSD-current, and is available at:

        ftp://ftp.NetBSD.ORG/pub/NetBSD/misc/security/patches/19990120-accept

    One workaround also is to run servers under tcpserver:

        http://pobox.com/~djb/ucspi-tcp.html

    tcpserver handles a single TCP port with a simple accept() loop.