Limitations on custom NFS mount authorization on Solaris
As it turns out, there are some limitations with our custom NFS mount
authorization hack that we've discovered.
First, Solaris 10 puts some security restrictions on what
do; the specific bit that we ran into is it can't
shell scripts. Mountd can make outgoing socket connections, so we got
around this by putting most of the complex work in an inetd-spawned
'daemon'. (There is probably a way to turn this security feature off,
but we didn't bother trying to find it.)
Second, things won't stall endlessly waiting for an answer to an NFS mount authorization. I don't know how long the various timeouts are, but there is definitely a limit on how much time your authorization code can use. This probably won't be a real limit in most environments, since the timeout seems to be at least several seconds, but bear it in mind.
We've also seen indications that mountd will only allow a certain (low) number of outstanding mount requests; my current guess is 20. Once it hits the limit, further requests are either dropped or get permission denied errors (it's not clear which, and we've lacked the time to debug things in detail when the issue has come up). This is also going to be an issue if your authorization code can take some time.
Finally, it seems that under some circumstances some part of the overall
system will cache the answers to mount requests, with the effect that
that an authorization decision can be 'sticky' for some amount of
time even if re-running the
innetgr() query from scratch would get
a different answer. It's possible that this is mostly for permission
denied answer, as spurious mount denials are when we notice this.
(Thus, this is probably not the right hack for you if your code needs
to take a shot at absolutely every mount request
mountd handles, no
All of this is inevitable given that the entire thing is a hack; one
can't expect the rest of the system to cooperate perfectly, the way one
could if this was a real feature. It follows that the more your code
deviates from normal
innetgr() behavior, the more possibility there is
for something to go wrong. If you need a seriously different NFS mount
authorization scheme, you may have to hack the OpenSolaris mountd code
base directly (and hope that it works okay on regular Solaris 10, which
it may not).
What you can't do before you drop setuid permissions
Let us suppose that you have a program that is setuid root but that usually drops its setuid status and reverts to running as the user that ran it. Of course you want to do this as early as possible to reduce the potential security risks, but at the same time you might want do some operations while still root (for reasons of either necessity or convenience in your code structure).
Consider the following tempting sequence, presented in pseudo-code:
Innocently, one would think that this code is harmless and safe. One
would be mistaken; this code is wrong and buggy. If the user's home
directory is on NFS and has restricted access permissions, the
will fail, because root has less permissions than a normal user when
working over NFS.
Now, consider this sequence (and assume that
$HOME is secure,
since this is just pseudo-code being written for clarity):
This code is not just buggy, it is a security exposure. It is buggy
for the same reason that the first code is (root may not be able to
$HOME/.config, although the user could), and it is a security
exposure because the user can make your program open anything on the
system with root permissions. Even assuming that there is no way at all
to make your program print out any part of the contents of the user's
(apparent) configuration file (either correctly formatted or full of
syntax errors), there are things that cause side effects when opened and
(And you cannot fix this.)
I don't know what you can safely do before dropping setuid permissions; it's a dangerous and hard problem that I don't know enough about to have an opinion beyond 'as little as possible'. But I do know that you definitely can't do either of these things.
(Now you can probably guess why I was tracing a setuid Linux program, and why I redacted the program name.)