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: