Subject: Re: Addition to force open to open only regular files
To: None <tech-kern@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: tech-kern
Date: 11/20/2000 18:49:39
[ On Monday, November 20, 2000 at 15:01:46 (-0800), Bill Studenmund wrote: ]
> Subject: Re: Addition to force open to open only regular files
>
> Also, everyone is focusing quite strongly on HOSTALIASES. But it is NOT
> the only thing which needs the ability for a library to open a file passed
> in by an untrusted source. Pretty much EVERY library routine which opens
> files whose names can come in via environment varialbes needs this
> protection.
Once upon a time in the very early days the access(2) call was the
feature designed to provide this protection.
Now that race conditions between access(2) and open(2) have been easily
demonstrated, and especially since they've been exacerbated by symlinks
(once upon a time set-ID programmers didn't have to worry about links to
/etc/shadow because it was on another filesystem, so race condiditons
were far less dangerous a threat than they are today), the best feature
to date to close these holes is something very much along the lines of
open_as() as it has been described in this thread.
Note that O_REG_ONLY does not come even close to fixing the access(2)
race condition -- it only fixes the immediate problem of privileged
programs accidentally opening device files, and it does so not by
checking permissions, but rather forcing the application code to do that
checking in a round-about manner (i.e. by re-implementing the guts of
access() with some more additional checks). The only difference between
environment variables that can (optionally) specify arbitrary pathnames
to be opened and other kinds of access()/open() race conditions is that
if the library programmer didn't think to call access() then the
crackers don't have to exploit any race conditions to get the desired
"effect".
Open_as() will completely fix this entire class of problems in one
elegant and simple fashion.
(NOTE: Library routines need not worry about getuid() not returning the
original invoker's UID. Any set-ID program that does setuid(getuid())
before calling a library that might want to use getuid() to find the
invoking user's UID is either not in need of such protection, or well
beyond the help of any library routine. Note also that it's impossible
to avoid setuid() resetting all traces of the original user's identity
without breaking the entire setuid paradigm too, or at least not without
adding another set of system calls to set and get it separately, just as
some trusted-Unix implementations have done.)
> So we have a problem where lots of routines called by many programs need
> to be able to to open a file without worrying that the program/library
> routine has just been tricked into doing something at higher privilege.
>
> We can either change a lot of programs, or we can make a simple kernel
> change and add a new library routine which does the right magic dance. I
> think the latter will represent a lot less work and fix a number of
> security holes all at once.
Yes, exactly -- I agree 100%.
However it would be foolish to believe that fixing only the library
routines to use open_as() will eliminate the problem. All set-ID
programs must still be audited to see if they also need to make use of
open_as().
--
Greg A. Woods
+1 416 218-0098 VE3TCP <gwoods@acm.org> <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>