Re: [RFC] Capabilities still can't be inherited by normal programs

From: Andy Lutomirski
Date: Wed Dec 05 2012 - 14:32:57 EST


On Tue, Dec 4, 2012 at 5:54 AM, Serge E. Hallyn <serge@xxxxxxxxxx> wrote:
> Quoting Andy Lutomirski (luto@xxxxxxxxxxxxxx):
>> >> d) If I really wanted, I could emulate execve without actually doing
>> >> execve, and capabilities would be inherited.
>> >
>> > If you could modify the executable properties of the binary that has
>> > the privilege to wield a privilege then you are either exploiting an
>> > app bug, or doing something the privileged binary has been trusted to
>> > do.
>>
>> That's not what I mean. I would:
>>
>> fork()
>> munmap everything
>> mmap ld.so
>> set up a fake initial stack and the right fd or mapping or whatever
>> just to ld-linux.so
>>
>> That's almost execve, and privilege inheritance works.
>
> But of course that is why you only want to fill fI on programs you trust
> not to do that. What you are arguing is that you want to give fI on
> programs you don't trust anyway, and so heck why not just give it on
> everything.
>

Huh? I'd set fP on a program I expect to do *exactly* that (or use
actual in-kernel capability inheritance, which I would find vastly
more pleasant). If I give a program a capability (via fP or fI & pI),
then I had better trust it not to abuse that capability. Having it
pass that capability on to a child helper process would be just fine
with me *because it already has that capability*.

The problem with the current inheritance mechanism is that it's very
difficult to understand what it means for an fI bit or a pI bit to be
set. Saying "set a pI bit using pam if you want to grant permission
to that user to run a particular program with fI set" is crap -- it
only works if there is exactly one binary on the system with that bit
set. In any case, a different administrator or package might use it
for something different.

Suppose I use the (apparently) current suggested approach: I install a
fI=cap_net_raw copy of tcpdump somewhere. Then I write a helper that
has fP=cap_new_raw and invokes that copy of tcpdump after appropriate
validation of parameters. All is well.

Now I want to grant only a subset of users permission to run ping. So
I modify ping so it's cap_net_raw=i (not p) and grant those users
pI=cap_net_raw.

The end result: I introduced a security hole: the users with
cap_net_raw=i can run tcpdump *without validation via the helper*.
Oops.

The fundamental problem as I see it is that fI and pI's behavior is so
odd that the significance of setting some of those bits varies and is
likely to be used, if at all, in conflicting ways.

> Anyway, implementing the features you want in a new module is encouraged,
> so long as the behavior of existing module stays the same.

I'll think about it some more and do it possibly using a sysctl.
Adding this kind of stuff in a module is asking for even worse
incomprehensibility of which capability bit means what.

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