Re: [patch 2.1.97] more capabilities support

Andrew Morgan (morgan@transmeta.com)
Sun, 19 Apr 1998 19:43:31 -0700


Albert,

[Please Cc: me with replies - thanks.]

> > One of the critical things about the capability model is the movement
> > away from having executables spontaneously acquire privilege by simply
> > being invoked.
> >
> > This is one of the main problems with the historical suid model: a
> > program gets all the power when it starts up. There are frequently
> > new attacks on programs that exploit such a feature. Passing command
> > line arguments that overflow a stack comes to mind...
>
> I think that is terribly wrong.
>
> 1. overflow stack
> 2. run code to enable super power <-- duh
> 3. run code to do bad stuff

OK, bad example. :*]

The real problem here is that it is hard to defend against poorly
written code that requires privilege. The benefit from capabilities
over the setuid case is that you can limit the damage...

> This looks far easier to bypass than the anti-exec patch,
> which can be bypassed under just the right conditions.
> For this, you don't even need to know the layout of the
> executable, libraries, and loader.

[If you don't mean the no-stack exec patch that Solar Designer made,
could you explain what you mean here? Off-line if appropriate. Thanks.]

> [ .. we need a "bounding set" .. ]

To address your suggestion of needing a "bounding set", I hope to show
with the following example that this is actually accommodated within
the current model.

Consider a dangerous command like 'rm'. Everyone needs to use it to
maintain their own files but, traditionally, in the hands of an admin
user like root no file is safe.

It is instructive to see how root's historic ability to delete
arbitrary files is made available to a select set of users without
risking 'nobody' from stealing this capability. The key thing is the
pI capability.

These are the implemented rules for propagating capabilities following
a sys_exec() call:

pI' = pI
pP' = fP | (fI & pI)
pE' = pP' & fE [NB. fE is 0 or ~0]

For the purpose of this discussion (and without loss of generality ;^)
we shall say that each of these symbols represent just the "remove
arbtrary files" capability (CAP_FOWNER).

The 'rm' executable is given the following file-capabilities:

fP = 0; fI = 1; fE = 0.

Now, consider two users: nobody and admin.

'nobody' logs in and is given a shell. Login arranges that the shell
nobody runs has the following Inheritable capability: pI = 0.
Similarly, the shell runs with pE = pP = 0.

'admin' logs in and is given the same shell. Login notices that
'admin' is a trusted user so, before exec()'ing the shell, it arrages
that pI = 1, and pE = pP = 0.

Here, we walk through the act of running 'rm' from the perspective of
each user:

'nobody's shell (pI = pE = pP = 0) invokes 'rm' (fP = fE = 0; fI = 1)
the new 'rm' process runs with (pI' = 0, pP' = 0; pE' = 0) => NO
CAP_FOWNER capability :^)

alternatively,

'admin's shell (pI = 1, pE = pP = 0) invokes 'rm' (fP = fE = 0; fI = 1)
the new 'rm' process runs with (pI' = 1, pP' = 1; pE' = 0) => 'rm' is
thus PERMITTED to raise the pE' CAP_FOWNER capability! In order to do
this, 'rm' uses a system call. Of course, this is something it is
allowed to do because pP' is set. :^)

It is for this reason that the "bounding set" was dropped by POSIX as
superfluous. It is also why the "Inheritable" set is passed across an
exec() untouched.

The neat thing here is that the shell, which is common to both users,
is unable to make use of the Inherited capabilities because it has no
file capabilities with which to snag them.

I hope this explains the situation better and has properly addressed
your concern.

Best wishes

Andrew

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu