Subject: Re: O_REG_ONLY, O_NOFOLLOW, open_ass(), and other such beasts
To: None <lucio@proxima.alt.za>
From: Greg A. Woods <woods@weird.com>
List: tech-kern
Date: 12/06/2000 04:10:17
[ On Wednesday, December 6, 2000 at 06:32:03 ( +0200), Lucio De Re wrote: ]
> Subject: Re: O_REG_ONLY, O_NOFOLLOW, open_ass(), and other such beasts
>
> Secondly, it has been nagging me for a while that the setid
> functionality is flawed in an intractable way: it is decoupled from
> the actual program code by being a property of the i-node, not the
> executable.
> 
> What I want to suggest may not solve any problems, but it will
> reduce the likelihood of accidents: if normal crts (the runtime)
> actually were to perform an obligatory set?id(get?id()) before
> starting main(), it would take linking with a special runtime to
> activate (well, inhibiting de-activation) of setid executables.
>
>[[....]]
>
> The issue really remains that it is a trivial system administration
> task to make an executable setid, which unfortunately does no
> checking of the reliability in such context of the underlying code.
> Ideally, one should want a certification suite that all potential
> setid programs should satisfy before the set?id bits can be set.

There's certainly lots of merit to the underlying idea that you're
suggesting here.

Note that there's already a rudimentary implementation of such a
"certification" suite in the form of /etc/security and the tools it uses
to scan the filesystem on a nightly basis.  It's not nearly so
pro-active as a run-time check, and of course it still leaves all of the
rope in the hands of the system administrator....

Another idea for a real-time implementation would be to provide a simple
mechanism by which a process could stat() the i-node from which it was
started.  Such a mechanism would allow one to implement a check in the
startup routine that tested the set-ID bits of the process image file
and thus the program author would be able to have control over whether
or not the process would continue to execute if it wasn't expecting to
be set-ID (or whether it simply logged the violation, or sent e-mail to
someone, halted the system, or whatever :-).  Of course you'd probably
want to first check to see if getuid() == geteuid() before doing
anything drastic so that the real superuser could still get things far
enough along to fix the "error" without having to boot from some other
media.

With this kind implementation if some foolish admin tries to make
/bin/sh setuid-root, for example, all you'll end up with is a
non-functional system since no new process started from /bin/sh by an
ordinary user would ever continue executing long enough to do anything
useful.  I like this a lot better because it actually causes a noticable
and unavoidable failure when someone screws up by turning on set-ID when
the programmer didn't plan for it.  With your scheme things continue
working transparently, perhaps with just a log entry being generated,
and I don't think that's strong enough punishment!  :-)

Control over such mechanisms could be as simple as allowing the
programmer to define a global variable and initialising it at
compile-time to a value that has the desired effect, and by providing a
default definition of such a variable in libc which would have the
opposite effect.

Note that such mechanisms would still be defeatable by patching the
binary (or of course re-compiling), but at least you make them work a
bit harder to implement their stupidity!  :-)

I would also worry a bit about third party code, since who's to say that
the programmer who disables such a protection mechanism at compile time
really knows what he or she is doing (i.e. that the resulting set-ID
program properly handles its set-ID privileges)?  The danger of course
is that admins might be more likely to make incorrect assumptions about
the relative safety of set-ID programs that continue to function
properly when set-ID.  Right now the responsibility of using set-ID
really lies entirely with the administrator, but with such a mechanism
the admin might feel that some of the responsibility has been delegated
to the programmer, when in reality that's not really happened.

-- 
							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>