Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 1998 10:46:29 -0500 (EST)
From:      Robert Watson <robert@cyrus.watson.org>
To:        freebsd-security@FreeBSD.ORG
Subject:   Alternative approaach: Re: Would this make FreeBSD more secure?
Message-ID:  <Pine.BSF.3.96.981117102200.24312A-100000@fledge.watson.org>
In-Reply-To: <19981117084523.A17686@weathership.homeport.org>

next in thread | previous in thread | raw e-mail | index | archive | help
In my view, inetd provides most of the services we already require, in the
TCP case.  That is, inetd allows us to run unpriveledged server software
in such a way that it has access to priveledged ports (although *only* for
the purpose of receiving connections, and only on a specific port with
specific properties).  Additionally, I allows us to place wrappers in
between and perform filtering etc.  The only really reasonably argument
against inetd in all cases is that some high frequency connection events
load the system because of the constant fork/exec and subsequent loading
of the system.  In a few cases, such as sendmail, it is also nice to have
the daemon sticking around for the purposes of queue management and
redelivery events. 

It seems to me that we could retain the benefits of inetd at the same time
as reducing the cost of its approach.  That is, with only minor
modification to inetd and the daemons, we could use the SCM_RIGHTS file
descriptor over socket mechanism to provide daemons with their connections
as they come in.  This is not quite as low in cost as having the daemon
sit around spinning on an accept(), and then forking as needed or passing
it on, as it requires inetd to be involved.  But it does not require inetd
to be very involved -- certainly not to the point of fork()/exec(). 

Here are the details as I envision it, and any criticisms are welcome: a
new 'type' is added in inetd.conf -- presumably replacing the
'wait'/'nowait' field, perhaps 'socktrans' or such.  At start-time, inetd
forks and execs all daemons that are of this type, except that it leaves
open a socket as fd 3 for the child process, that can be read on.  Instead
of spinning on accept(), the child will now spin on recvmsg() with
appropriate arguments to receive up to N file descriptors.  Inetd now
binds the ports as it normally would, awaiting connections.  When a
connection comes in, inetd evaluates whether it is a valid connection
(possibly taking advantage of wrapper code, perhaps an allow/deny file of
some kind, perhaps logging it), and then transfers it over the socket to
the child.  In the event that the child closes the file socket, it can
always be restarted, improving reliability (if desired). 

This solution, of course, is oriented at the TCP crowd -- sendmail, httpd,
the normal suspects.  Given the cost of a TCP setup, and the
light-weight-ness of inetd, I do not think there will be that much of a
performance impact on most systems.  Clearly, there is no real benefit
for daemons such as sshd, other than providing a standard way for daemons
to listen -- sshd has to run as root so that it can switch to the account
of the user when required.

I'm not sure that this can address the UDP case.  I believe that in the
case of DNS (bind), the UDP responses have to come from the same port that
they are sent to; also, the resolution of interest is not 'connection' but
'packet'.  The cost of forwarding the packets to the process is higher
per-packet and therefore more likely to impede performance.  Similarly,
inetd would probably have to send the packet for the daemon.  The easier
approach might simply be to bind the socket, and then pass it off to the
child for further use.  Any time the child died (or released the socket),
presumably it could be restarted.  I'm not as satisfied with this case, as
it doesn't allow inetd to filter the 'connections'.  On the other hand, it
no longer requires the daemon to run as root. 

This solution requires no potentially suspect modifications to the kernel,
and no modification to the standard set of groups that would no doubt
upset people.  Mapping uids to port numbers is also a somewhat problematic
approach -- not very scalable, and no fun if you use a portmapper :).

Actually, that does raise the case of the RPC-based NFS suite.  In that
case, perhaps there could be an indication that 'any port will do' for the
port passed to the daemons, except the portmapper where only the
appropriate port will do.  In the general case though, the NFS suite
probably does require root access on both the client and the server, so
perhaps it is not a biggy.  And I'm not sure that we want to munge our
heads into the RPC code to rewrite it to use this mechanism? :)

Presumably we would also have to address the case where a daemon listens
on multiple ports (UDP and TCP, such as Bind).  Perhaps a solution might
in fact be to have a protocol by which daemons talk to bind using the
socket, such that they can in effect ask inetd to proxy bindings for them;
inetd.conf would be more of an ACL file on what it was willing to proxy.
That is a more serious change, however, and as it does not affect many
daemons, is something that could be overlooked for greater simplicity for
now.

My belief is that this should certainly perform well enough, and require
only minor modifications to sendmail.  For many web servers, I imagine it
would not represent a serious performance impact.  At the rate of a few
hits a second for a low-end web server (400,000 hits a day is only 5 a
second on average), transfering a few ancillary data packets has low cost.
Addressing the dual udp/tcp case by passing two sockets would deal with
some additional daemons, such as syslog and bind.

All existing daemons would continue to function unmodified, of course.

  Robert N Watson 

robert@fledge.watson.org              http://www.watson.org/~robert/
PGP key fingerprint: 03 01 DD 8E 15 67 48 73  25 6D 10 FC EC 68 C1 1C

Carnegie Mellon University            http://www.cmu.edu/
TIS Labs at Network Associates, Inc.  http://www.tis.com/
SafePort Network Services             http://www.safeport.com/


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.981117102200.24312A-100000>