Re: caps in elf, next itteration (the hack get's bigger)

Albert D. Cahalan (acahalan@cs.uml.edu)
Sat, 17 Apr 1999 00:59:56 -0400 (EDT)


David L. Parsley writes:
> On Fri, 16 Apr 1999, Andrej Presern wrote:

>> [...] marginal security gained by 'turning off' a capability in the
>> 'effective' set but leaving it 'on' in the 'permitted' set is exactly
>> zero, making the set of permitted capabilities effectively the set of
>> effective capabilities. In other words, your process is either able
>> to do something, or not able to do something - an extra syscall or
>> two makes no difference.
>
> Ok, I agree completely with this; I don't see any good use for fE, it
> really doesn't enhance security; if someone can explain to me why it
> might, I'd be interested (Ted?)

Andrej Presern seems to view security in a very mathematical way, without
concern for stupid human errors. It is true that you could just enable
all the rights you have and "rm -rf /" at will, but that requires full
control over the executable _and_ evil intent.

Reduced bits in the effective set gives you:

1. some protection from stupid mistakes
2. some protection from trusted executables with bugs

>> Furthermore, the POSIX privileges contain the third set of capabilities,
>> the inheritable set, which is also a design failure as it makes the
>> design to fail to contain the damage in case of a buggy privileged
>> binary. Once a privileged binary is broken into (for example at
>> runtime by means of a stack overrun), it can be made to spawn an
>> arbitrary child (such as a shell for example) that will inherit
>> the authority of a buggy parent, thus enabling an attacker to gain
>> unauthorized access in a useful form (a shell for example). [...]

This does not make a difference, since the stack overrun can _be_ a
shell after it loads some more code. There is no need to exec().
Using threads, the exploit code could even emulate multiple processes.

> Ok, this is what gave me pause; I've been considering how to design a
> system around our capabilities model, and pI' = pI can be a problem in
> many cases. I suggest we drop the fE concept, and use it instead as an
> inheritable mask, fM, and change the formula for inheritable to: pI' = pI
> & fM. This is nice for 'dead-end' programs, such as telnetd or httpd,
> which really shouldn't allow spawned process' to inherit from it.
> Instead, these should merely have CAP_NET_BIND_SERVICE for fP, for
> instance. Using this extension, you allow programs to inherit privs when,
> say, run by an administrator; but they inheritance will 'dead-end' with
> that program. This is good for, say, Ted's example of a trusted program
> calling 'more'.

I have a proposal (now fixed; it had some bad typos) that seems to
improve the capabilities system in a compatible manner. I propose min
and max data as follows:

pm Always set these.
pM If ~pM would be in pP' after the exec, then return -EPERM.
fm If these bits would not be in pP' after the exec, then return -EPERM.
fM Remove unset bits from pm. (?)

Calculation becomes something like this:

new_pP = old_fP | (old_fI & old_pI) | old_pm;
if(new_pP & ~old_pM) return -EPERM; /* getting prohibited caps? */
if((new_pP & old_pm) != old_pm) return -EPERM; /* not enough? */

(the rest inherits in the obvious or documented way)

If you missed the above, then you also missed some background discussion.
It is now at http://www.cs.uml.edu/~acahalan/linux/cap.txt

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