Subject: Re: Addition to force open to open only regular files
To: NetBSD Kernel Technical Discussion List <tech-kern@netbsd.org>
From: Matthew Orgass <darkstar@pgh.net>
List: tech-kern
Date: 12/04/2000 22:28:34
On Mon, 4 Dec 2000, Greg A. Woods wrote:

> (Obviously it makes a great deal of difference which ID you are running
> as when you call certain system calls! :-)

  Right, this is the issue.  When you call library routines, you have no
control over what they do.  If you limit privilege to the exact calls that
need it, then you limit the extent of privileged code.  While it is still
possible that libc open and such will do unintended things, it is much
less likely.  As you mentioned, this does nothing against bugs, but
something like HOSTALIAS would not have the tape rewind problem if run as
the real user.  It might result in incorrect behavior later, but it at
least avoids the immediate privileged use of tainted data.

> Well, you can't remove setuid() completely, at least not without
> inventing a whole lot of privileged daemons and incorporating a whole
> lot of authentication goo in your IPC (eg. kerberise everything in
> sight, including the kernel!).  I think there are already operating
> systems that don't make use of the setuid concept, and they're certainly
> not unix-like (though some claim POSIX.[12?] compliance! :-).

  It may never go away completely for compatibility, but it should not be
especially difficult (on a large change scale) to remove its use from the
base system and provide a means to disable it.  Many things that use
setuid (and all that are truely necessary for basic system operation)
should be done by appropriate kernel protection (new syscalls if
necessary).  The rest can easily be done with IPC.  An inetd type daemon
could be used to run the daemons only when necessary.

> I think I'll stick to multi-user systems that use setuid, at least for
> the time being.

  It certainly needs work to get there, but it is not exceptionally
difficult.

> However using IPC with carefully designed single-shot privileged
> set-ID programs is clearly the most secure way to design subsystems
> that have to make use of resources that require privileges to access.

  These should be started by an inetd type daemon, not by set-id.  This
way the user has no influence over the environment, cwd, or anything else
that might affect its operation.

> This is exactly what I was talking about in the example of how ftpd
> could still open socket bound to the privileged port #20 after having
> authenticated and authorised the logged in user and called
> setuid(login_user).

  Ftpd is a sepecial case due to the broken protocol.  This could be fixed
by allowing access to just that port to that process after setuid.  It
should also be possible to reserve ports to any user, so it may also make
sense to just always run as user ftp as you would with a long running ftpd
(perhaps with a mechanism to allow the kernel to apply permissions for
both ftp and the user when accessing files).

> I.e. the best systems security will come from *never* running big
> monolithic daemons as root, and from always permanently dropping
> privilege as soon as possible in any prgram which performs
> authentication and authorisation.

  Right, most daemons should be run as a dedicated user, not root.

> Of course once you've done all of this neither seteuid() nor open_as()
> would be necessary and we'd be back to just plain old setuid()!  :-)

  And, with one additional daemon, no set-id programs :).

> First off, please let us forget about setre*id() -- they're as good as
> dead and gone, especially for the purposes of this discussion since
> there are no programs using them left in the base system, and as yet
> I've not encountered any add-on programs that need them either.

  Until the libc major number is bumped they need to be supported for
compatibility.  It could be argued that it would be better to bump the
major and remove setre[ug]id, however until that happens compatibility is
required.

> Even for this particular point the issue is moot -- the current real ID,
> as returned by getuid(), is always going to be the correct one to use
> for the purposes of something like $HOSTALIASES or $TZ (with a tzfile).

  This is not true when setre[ug]id is used to swap the real and effective
ID.  In other cases, the real id would always be used.

Matthew Orgass
darkstar@pgh.net