Re: [PATCH] Capabilities, this time in elf section

Richard Gooch (rgooch@atnf.csiro.au)
Fri, 16 Apr 1999 12:04:26 +1000


Hi, David.

> Hi Richard,
>
> On Fri, 16 Apr 1999, Richard Gooch wrote:
>
> > David L. Parsley writes:
> > > Hi Albert,
> > >
> > > On Thu, 15 Apr 1999, Albert D. Cahalan wrote:
> > > > > haven't really given more than a few second's thought to the solution,
> > > > > evidenced by your misunderstanding about the immutable bit relationship.
> > > >
> > > > I'm not some kind of vegetable you know... (rudeness not appreciated)
> > > > While I think you are terribly wrong, I acknowledge that you have given
> > > > more than a few second's thought to the solution. I have too.
> > >
> > > Not everybody has done their homework on this stuff before speaking
> > > up. I now see that you obviously have done the required reading.
> >
> > Maybe I'm wrong, but the impression I've gotten from you, David, is
> > that whenever a new person pops up into this debate and disagrees with
> > you, you tell them they're ignorant (not reading beforehand, not
> > thinking, etc.).
>
> Richard, I'm not alone in thinking that not everybody had studied up as
> they should. When this debate first started, _I_ had not done my reading,
> and after I _did_ it changed the whole picture for me. So I figured
> others might easily have made the mistake I did.
>
> Here's an example of what gave me the wrong impression:
> --begin excerpt from prev.
> Me:
> > > We're not _granting_ capabilities, we're stripping away all the
> > > unneeded capabilities. Otherwise it runs 'full bore'. Are you
> > > saying that portmap should be run with _all_ capabilities? Or do we
> > > need to cripple root before running it? With setuid0, to strip away
> > > unneeded caps you need to make it, well, setuid0.
> Richard:
> > No! I already made this point last week. You only need suid-root to
> > *grant* caps. Any binary can have its CAP ELF section with a mask of
> > caps that are *removed*. There is no privilege needed for that.
> Me:
> Well, for one, the standard for capabilities doesn't exactly have a 'deny
> mask' as such; it would have to be done in the interaction of the current
> process' inheritable set and the file's inheritable set. You _could_ just
> put a flat 'deny' mask in there, but you get further from true
> capabilities, and the file owner can modify them.
> --end excerpt--
>
> Now, at this point I thought maybe you hadn't gone through the privs
> docs enough. What appears to be going on, however, is that I've
> been assuming we want to completely preserve the proper (designed)
> semantics of a capabilities system. It looks like that just isn't a
> design goal for everybody. (to quote Ted: 'capabilities lite') It's
> merely a disagreement I failed to see, and I made a bad assumption.

I'm not necessarily advocating "capabilities light". I'm definately
advocating a "capabilities practical" scheme, which obviously includes
NFS and similar support.

But I'm not convinced that "capabilities practical" means
"capabilities light". If it does mean that, so be it. Mind you, I have
yet to see this proven.

> Sorry about that, I don't feel at all good about insulting anybody.
> I thoroughly enjoy an interesting debate, and I hope I can learn to
> debate without being insulting.

I know. It's easy to flame or appear rude. Much harder to choose your
words so that you get the point across, including the intensity of
your belief, without coming across as arrogant, rude or flaming. We
all need to be vigilant. I certainly don't claim to be above it all.

> > You want privileged inheritable bits, fine. You can do that with
> > suid-root or with sticky+immutable. After all, the inheritable bits in
> > both cases are stored in the CAP ELF header. So to solve the security
> > problem, you drop privs on exec if they're not in the inheritable
> > mask. And you don't allow lusers to modify the inheritable mask.
> >
> > IIRC, Pavel was suggesting lusers can modify the inheritable mask. I'm
> > not supporting that.
> >
> > Where I think you are concerned with the suid-root scheme is that it
> > implies /bin/sh must be suid-root if you want it to inherit the caps
> > of a calling god process.
>
> sh, cp, tar, ... lots.

Sure. But in your sticky+immutable scheme (or any variation), or in
fact a scheme where cap masks are kept in the FS metadata, the grant
and inherit masks require privilege to modify.

> > I don't see a problem with that. Whether
> > you have a suid-root or a sticky+immutable magic flag, either way,
> > /bin/sh *is* special.
> >
> > Now, I think that you think that a suid-root /bin/sh implies that
> > when you run a non-caps kernel, a random luser then does /bin/sh and
> > boom! Crack, crack, crack.
> >
> > Well, this isn't the case. If you read one of my earlier messages, I
> > suggested putting the suid-root+CAP ELF header stuff into user
> > space. So that means when you run the setcap programme, you either
> > edit the binary (if it's statically linked) to insert some magic code,
> > or ensure the dynamic linker has the magic code.
> >
> > This magic code does all the work of raising caps if euid=0, if the
> > kernel has caps, and then sets euid to the stored euid in the
> > header. On the other hand, if the kernel doesn't have caps, the magic
> > code can elect to refuse to run the binary, or to set euid=uid, or
> > whatever.
> >
> > This means you can safely switch between a caps-enabled and a non-caps
> > kernel. You can elect, on a per-binary basis, what should happen when
> > running a privileged binary on a non-caps kernel. This gives
> > incredible flexibilty, allowing a sysadmin to configure the level of
> > paranoia they wish.
> >
> > This scheme also has the advantage of running over NFS, CODA, ISO9660,
> > AFS and so on. You can run a special auditing programme at boot time
> > if you want to check the integrity of the dynamic linker, for extra
> > paranoia.
> >
> > And best of all: it's all in user space!
>
> This just doesn't sound attractive to me, mainly for the complexity
> that's not required. It just seems like a long way to stretch for
> secure operation over a remote fs. Perhaps something like this
> could be layered over a sticky/immutable solution for the local fs;
> honestly I'll need to re-read what you've just said several times to
> understand it exactly. Or you could go into more detail for me,
> with a concrete example.

I've thought a little more about my scheme, and realised I had a
flaw. I've redesigned it to fix this. It also makes parts of my scheme
the same as yours, without the problems of yours, and with the extra
benefits of mine.

In addition, my scheme gives you a pretty flexible system for
increasing security on non-caps kernels. You can easily set things up
so that when root runs another binary, the uid and euid are set to
nobody, if that binary has no capability header, or doesn't have any
inheritable caps set. The only thing you can't control is statically
linked binaries without the magic code. But if you're setting up a
secure system, you'd relink those anyway.

Just as in your scheme, the kernel checks the magic flag (suid-root
for me, sticky+immutable for you). If that's not present, caps are
dropped, irrespective of the euid. If the magic flag is present, the
grant and inherit masks are applied.

At this point, for a caps-enabled kernel, our schemes are the same,
except that mine works over NFS and such.

Where things differ is that with my scheme, the capedit programme
inserts a small amount of magic code into a binary (if statically
linked), or into the dynamic linker (if dynamically linked), so that a
suid-root binary will fail (or change uid/euid) unless the ELF CAP
header has grant or inherit bits set. This code is only run on
cap-less kernels.

This does two things:

- it prevents the problem of luser running /bin/sh (which is suid-root
so a cap-enabled kernel will allow inherits) and getting a root shell

- it provides *some* of the security benefits of file-based
inheritance, so that any dynamically linked binary (or a new
statically linked binary) can elect to drop root privileges.

For the non-caps kernel case, the magic code can be used to prevent
some/most/all binaries running as root.

And remember, just because you have all these suid-root binaries
floating around, it doesn't mean root can get cracked, or that you
have a root account.

I hope I've explained how my scheme works.

> Note that now I'm more interested in the solution proposed in my
> last reply to Ted T'so. WRT remote fs's and iso9660, UMSDOS, etc.,
> it would still have basically the same properties as the
> sticky/immutable solution. Which, I guess would still be
> unnacceptable to you.

Indeed. If I decide I want to trust the fileserver to hand out
privileges, I want that flexibilty. Your scheme prevents that, because
it opens up a security hole (any luser can set the sticky bit, or you
require the immutable or some other non-Unix flag).

You're taking away that choice.

Regards,

Richard....

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/