Subject: Re: Addition to force open to open only regular files
To: NetBSD Kernel Technical Discussion List <firstname.lastname@example.org>
From: Greg A. Woods <email@example.com>
Date: 11/17/2000 20:55:58
[ On Friday, November 17, 2000 at 17:30:10 (-0700), Warner Losh wrote: ]
> Subject: Re: Addition to force open to open only regular files
> In message <20001117180038.7881D4@proven.weird.com> Greg A. Woods writes:
> : I'm not conviced that's even the obvious solution. open_as() is more
> : obvious, and a set of filesystem-ID credentials is perhaps the more
> : generic solution to cover all filesystem accesses, though it's
> : potentially just as dangerous as ID swapping (I haven't yet explored the
> : full range of possibilities with it yet).
> But as has been pointed out, you have no way of knowing the saved uid
> to pass to open_as. :-(. Although we could make an excellent guess in
> crt0 and crib that away for later issuing.
My proposal for new getsuid(2) and getsgid(2) calls intended to retrieve
the saved set-ID credentials is really only put forth to be pedantic.
You can easily determine them if you want because they are equivalent
to the effective-IDs when the process first starts. It's just a matter
of squirrelling away user-land copies early on.
However I'd rather be able to get these values from directly from the
kernel at any old time rather than have to keep track of them in
Of course if some ignorant admin puts the set-ID flags on some binaries
that aren't expecting it then the program's going to stand a good chance
of doing bad things -- putting a check in every program to cause it to
bail if it's set-ID when it doesn't expect to be is probably not that
productive of an idea (though it may not hurt for the super paranoid).
Conversely if the set-ID flag(s) is(are) removed from binaries that are
expecting and needing it, then the issetid() call you mention in another
message can be helpful for diagnosing the problem, but I don't think
it's really necessary except perhaps in a library call that might be
used both before and after a set*id() call (I can't quite imagine a real
example here though).
HOWEVER, in most cases it's not the saved-set-ID credentials that you'd
want to pass to open_as() anyway -- but rather the real-IDs.
Indeed it would not be safe to be able to use the saved-set-ID
credentials in open_as() after priviledges have been released for the
same reasons that sete*id() is not necessarily safe. (In fact I'd
rather just get rid of saved-set-ID credentials completely, but POSIX
has unfortunately embedded them into the specs for now.)
In fact it may be possible to show that open_as(2) need not do anything
but operate as if it were the real user, just as access(2) does -- i.e.
that it does not need any parameters different than open(2).
This wouldn't solve my problem with smail where I want to be able to
safely open an arbitrary user's ~/.forward file, however that problem
can easily be solved by splitting the program into a main daemon that
runs set-group-ID and by having a set-uid-root executable that's owned
by the same group the daemon runs as, and executable only by that group,
that would return the contents of a specified user's ~/.forward file on
stdout or some such. I.e. reverse the roles in the code so that the
majority of it runs as the "mail" group and only tiny specialised
programs run set-uid-root. (In fact for a mailer the ~/.forward reader
doesn't have to be too protected since the content of such files is more
or less public knowledge anyway -- and if you're paranoid about such
information you can still store it safely in the Sys-V "Forward to"
format in the spool file, or in some other collection of files owned by
the user but in some common hierarchy away from $HOME, where it's
accessible by the "mail" group and thus a set-uid-root reader and local
delivery program is not necessary.)
Similarly it may not really be necessary to have a full setfuid(),
setguid(), and setfgroups() set of calls -- there could be just one
toggle switch that says to do filesystem accesses either as the real
user, or as the effective user, without having to use sete*id().
Greg A. Woods
+1 416 218-0098 VE3TCP <firstname.lastname@example.org> <robohack!woods>
Planix, Inc. <email@example.com>; Secrets of the Weird <firstname.lastname@example.org>