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);