COMMAND

    inetd

SYSTEMS AFFECTED

    This may apply to all known versions of inetd.

PROBLEM

    Jeff Forys found  following.  For  a tcp/nowait connection,  inetd
    invokes accept(2) for each pending connection; this call returns a
    file descriptor associated with the new connection.  Twelve  years
    ago, code  was added  to inetd  to detect  "failing servers".  The
    heuristic that identifies  a failing server  is one that  has been
    invoked  a  large  number  of  times  over some specified interval
    (e.g., more than 128 ftp  services started in 60 seconds  may flag
    the ftp service as "failing").  These compile-time constants  vary
    depending on vendor.

    The problem is that, when  a failing server is detected,  the code
    neglects to close the  file descriptor returned by  the accept(2).
    Pummel  one  of  inetd's  tcp/nowait  services  so that it exceeds
    the failing server threshold and logs a message like:

        svc/proto server failing (looping), service terminated

    If your inetd has this bug, it will have leaked a file descriptor.
    You'll have to come up with your own OS-independent way of finding
    out how many file descriptors your inetd process is holding  open.
    Implications  would  be  someone   with  ample  free  time   could
    orchestrate  an  attack  buy  pummeling  services  until the inetd
    process finally runs out of file descriptors thus rendering  inetd
    useless to any new connections that require a new descriptor.

SOLUTION

    Here are a couple variations of the same fix.  Hopefully, one will
    work for you.  If not,  the following two patches should give  you
    a good clue where to look  in your source to determine whether  or
    not you are affected by this problem.  If you examine the  source,
    you  will  see  a  call  to  close_sep(sep).   Note  that,  in the
    tcp/nowait case, this does not  actually close the fd returned  by
    accept(2).   Rather,  "sep"  holds  the  control  socket  that  is
    listening  for  connections  on  that  port; Since the service was
    identified  as  "failing",  the  port  is  shut  down  (it will be
    reopened after some specified timeout).

    *** inetd1.c_orig       Fri Jun 26 13:03:55 1998
    --- inetd1.c    Fri Jun 26 13:05:24 1998
    ***************
    *** 362,365 ****
    --- 362,368 ----
                            "%s/%s server failing (looping), service terminated",
                                                sep->se_service, sep->se_proto);
    +                                       if (!sep->se_wait &&
    +                                           sep->se_socktype == SOCK_STREAM)
    +                                               close(ctrl);
                                            close_sep(sep);
                                            sigsetmask(0L);

    *** inetd2.c_orig       Mon Sep 22 02:23:24 1997
    --- inetd2.c    Fri Jun 26 12:40:36 1998
    ***************
    *** 462,465 ****
    --- 462,468 ----
                            "%s/%s server failing (looping), service terminated",
                                                sep->se_service, sep->se_proto);
    +                                       if (sep->se_accept &&
    +                                           sep->se_socktype == SOCK_STREAM)
    +                                               close(ctrl);
                                            close_sep(sep);
                                            sigsetmask(0L);