Re: Sharing credentials in general (Re: [GIT PULL] kdbus for 4.1-rc1)

From: Andy Lutomirski
Date: Mon Apr 27 2015 - 12:13:40 EST


On Mon, Apr 27, 2015 at 8:50 AM, David Herrmann <dh.herrmann@xxxxxxxxx> wrote:
> Hi
>
> On Mon, Apr 27, 2015 at 4:57 PM, One Thousand Gnomes
> <gnomes@xxxxxxxxxxxxxxxxxxx> wrote:
>>> But this is not how authorization with polkit works (or anything
>>> similar to polkit). The authorization-framework is totally separated
>>
>> Thats a detail which is changeable
>
> It's not a detail, it's a design choice. But see at the end..
>

It's also completely irrelevant to the present discussion. It makes
no difference what code or policy is embedded in what framework.

(It's also actively problematic. As it stands, I, as a logged in
user, have no idea how to waive my permission to reboot the machine on
a regular Fedora install. Dbus and polkit have obfuscated it to the
point that it's already quite difficult to undertsand. This bit me a
couple days ago.)

>>> from the client that accesses a service. The client asks a service
>>> provider to perform an action. The service provider then asks the
>>> authorization-framework, whether the client is authorized to run the
>>> action.
>>
>> This is not good design IMHO. The client should always be indicating it
>> intends to pass on the credentials it has. That stops privileges leaking
>> or programs being tricked into things.
>
> If all you pass along is your identity, you cannot "leak a privilege".
> If you run a program as someone privileged and you don't want the
> program to run as such a user, well, then you better not run it as
> such a user..
>
> We don't do setuid or setcap. A caller always has full control who to
> run a program as. Choose that wisely, don't make the program protect
> itself against the user. On the contrary, if a program is called with
> elevated privileges, then this is an explicit decision of the caller
> we must respect.

Who is "you"? In the future universe where kdbus takes over as the
main way of doing privileged things, people most certainly will run
kdbus clients setuid or setcapped.

>>> Without LSM, we don't have such a unique identifier. Therefore, we
>>> send the UIDs+GIDs+CAPs+NAMEs combination. Those we pass on to the
>>> authorization framework, to decide on whether the peer is privileged.
>>> And we believe those should be mandatory, not optional, just like the
>>> seclabel we send if an LSM is active.
>>
>> The mashed up caps and names really ought to be replaced by something
>> better. Especially the names. Would it make sense to put some kind of
>> security label on the executable and pass that instead ? So instead of
>> all the caps and names crap you label the executable itself as having
>> "kbus:awesomerebootpower" or whatever so the kernel can see that cleanly
>> as a label that's basically a kbus namespace capability ?
>
> (it would be lovely if you did not call my code 'crap')
>
> But this is the essential difference in our design. We don't want code
> to be aware of their privileges. We want privileges to be attached
> externally to an identity. Thus, a program should always assume it is
> privileged to do whatever its purpose is. If its purpose does not fit
> you, you better not call it. In all other cases, a "privilege leak"
> would just result in the program running as expected.
>

Two answers:

1. This is severely inconsistent with other things I've heard recently
from the kdbus camp. Lennart wants clients to use caps and adjust
them. This would involve those clients being very much aware of their
privileges, and their privileges would not "be attached externally to
an identity". Please make sure you actually understand your security
model before you try to justify it.

2. This is a nice thought, but it doesn't work in practice. Sorry.
I can give you a big pile of CVEs from last year if you like, or I can
try explaining again.

The issue boils down to what type of privileges you want to assert and
over what object you want to assert them. Suppose I have a method
"write". When I call it, I do Write(destination, text). In your
model, it's basically never safe to do:

Write(client_controlled_destination, "Log message: client asked me to do xyz");

because the client cause xyz to be "--\nDELETE TABLE people;" or
similar and the server *can't* Write without that Write exercising the
full authority of the server's identity.

Again, we have had Real Exploitable Bugs (tm) in the kernel in
implementations of the write(2) syscall because of this issue. When I
raised those issues (with exploits!) people made very similar
arguments to yours along the lines of "no, sudo is buggy because it
writes to stderr". Sorry, but you're missing the point here. Even
highly privileged programs need to be able to perform unprivileged
operations.

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