[7273] in bugtraq

home help back first fref pref prev next nref lref last post

inetd can leak file descriptors +FIX

daemon@ATHENA.MIT.EDU (Jeff Forys)
Wed Jul 15 13:30:42 1998

Date: 	Tue, 14 Jul 1998 23:00:08 -0400
Reply-To: Jeff Forys <jeff@FORYS.CRANBURY.NJ.US>
From: Jeff Forys <jeff@FORYS.CRANBURY.NJ.US>
To: BUGTRAQ@NETSPACE.ORG

Index:  usr.sbin/inetd/inetd.c

This may apply to all known versions of inetd.

Description:
        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).

Repeat-By:
        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.

Security-Implications:
        I suppose 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.

Fix:
        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);
---
Jeff Forys

home help back first fref pref prev next nref lref last post