Subject: bin/8253: inetd builtin services bug
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dholland@eecs.harvard.edu>
List: netbsd-bugs
Date: 08/22/1999 19:10:51
>Number: 8253
>Category: bin
>Synopsis: inetd builtin services don't close listen sockets
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Aug 22 19:05:00 1999
>Last-Modified:
>Originator: David A. Holland <dholland@eecs.harvard.edu>
>Organization:
- David A. Holland | VINO project home page:
dholland@eecs.harvard.edu | http://www.eecs.harvard.edu/vino
>Release: NetBSD-current of 19990822
>Environment:
System: NetBSD bordeaux 1.4 NetBSD 1.4 (GENERIC) #0: Fri May 7 12:27:31 PDT 1999 perry@cynic.cynic.net:/usr/src/sys/arch/i386/compile/GENERIC i386
I have not actually tested this; I don't have root on a NetBSD box
at the moment. However, as far as I can tell from the -current source,
the problem does affect NetBSD. I found it when testing a set of
massive changes to Linux's inetd.
A friend reports that it definitely does affect OpenBSD. ;-)
>Description:
Some of the inetd builtin services fork, to avoid having inetd hang
while they run. This is fine, but the child processes get copies of
inetd's listen sockets, and they don't get closed.
Consequently, if one of these builtins gets left going when you kill
and restart inetd, the restarted inetd won't be able to bind to any
of the ports it's trying to listen to.
This counts as a denial of service attack, I suppose, although it's
not a very serious one.
Also, if you ask inetd to run the builtin services as someone other
that root, it ignores you.
>How-To-Repeat:
telnet localhost echo
<switch windows>
kill `cat /var/run/inetd.pid`
/usr/sbin/inetd
<examine syslog>
This will, obviously, only work if you are so foolish as to have
one of the forking inetd services enabled (echo, discard, chargen,
tcpmux).
>Fix:
The code presently has
if (sep->se_bi) {
(*sep->se_bi->bi_fn)(ctrl, sep);
} else {
[uid/gid manipulation]
[dup2 calls]
[RLIMIT_NOFILE frobbing]
execv();
}
where it should do all the work except the actual execv before
checking if it's a builtin.
Also, since NetBSD seems to have changed inetd to close
listening sockets by using the close-on-exec flag instead of
going through and closing them, a loop of the latter sort is
needed in the builtin case.
Sorry I don't have an exact patch; hopefully in a couple weeks
I'll have a NetBSD machine again.
>Audit-Trail:
>Unformatted: