Re: Issues with capability bits and meta-data in kdbus

Andy Lutomirski
2015-04-22T03:20:13Z

On Tue, Apr 21, 2015 at 7:32 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Tue, Apr 21, 2015 at 6:54 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>
>> If kdbus were a general purpose IPC tool
>
> .. but it's not ..
>
>> and if the libraries would
>> expose nice knobs like "set this flag if and only if you want to
>> assert CAP_WHATEVER to the server", then maybe this would be okay.
>
> I really don't agree.
>
> The whole notion that you should be able to be anonymous when
> communicating is *wrong*.
>
> Now, when you talk across machines using TCP, there's no identity that
> you can trust, so anonymity is kind of enforced. But locally, if you
> want to connect with somebody else, I actually think that tryin gto be
> anonymous is just stupid - and more than that - plain wrong.
>
> Yeah, if you do a pipe, that's one thing. You don't "connect" to
> somebody else with a pipe, you just create both end points. So there
> is little point in having identifying information for pipes. But when
> you connect to a service, it just *makes sense* for the other end to
> know about you. They should know your user ID, they should know your
> identity (pid or whatever), and they should know your capabilities.
>
> If you don't want that, then you use some anonymizing service, and it
> because *your* problem. But a server that gets connected by different
> people should know who it gets connected by.
>
> Unix domain sockets simply got this wrong.
>
> I don't think thi sis the problem of kdbus. There may be *other&*
> problems, but I think it's very reasonable to just have as a basic
> *requirement* that when you get connected, you get to know who
> connects you, and what their rights are. Because it really *is*
> something fundamental, and something important to know. Is it some
> random nobody, or is it a system service?

Where do you draw the line?

In the dbus dream world, if I type "wget
http://www.example.com/foobar", then my DNS resolver knows the whole
URL I'm downloading (cmdline), that I'm wget (or that I'm pretending
to be wget), that I inherited these capabilities from my caller (using
the totally broken capability inheritance model, but whatever), that I
started at time such-and-such (breaking CRIU), that my gid is
such-and-such, etc. That DNS resolver ideally should sandbox itself,
but it now *necessarily* has this information leak in to its sandbox.

It gets worse. My little tray notifier widget that shows the progress
bar also learns all this information. Heck, my tray notifier probably
also finds out what capabilities systemd is holding every time I plug
in a USB stick, because of broadcasts.

It also conflates information-for-the-hell-of-it, auditing, and
authorization. When I write a program that tries to drop privileges,
I need to know *what those privileges are*. When every damn attribute
of my process might be seen as a privilege by whatever daft daemon,
system or otherwise, I'm talking to, it's *really hard* to figure out
what's exposed if I get compromised.

>
> If I was a service writer, that would be *the* most basic requirement
> I would have. No ifs, buts or maybes about it.

Sorry, but I don't believe you. Do you really need to know all this
random information about everyone who connects? Why only for local
users? Why is it different over a network? Which of those pieces of
information are you going to use for authentication? Which are
potential information leaks for a reason that didn't even exist when
you wrote your service?

If I were a service writer, I would define what privileges are needed
to do what, and I would require those and no more. I don't want to
know more, because everything else I learn for no good reason is a
potential security problem.

As a concrete example, remember all those lovely euid and caps bugs we
found in write(2) a couple years ago? The only reason those bugs were
possible is because write(2) is implemented in the kernel, and the
kernel can do whatever the hell it wants including incorrectly looking
at caps in write(2) and those bugs were IMO especially embarrassing
because all of the code needed for the stupid interaction that caused
those bugs is in the kernel tree. Everyone "knows" that write(2)
*must not honor effective caps*, but a lot of people forgot.

I'd much rather have dbus not tell the peer random stupid things about
me that the peer can fuck up than have dbus tell the peer all this
stuff for the hell of it, because the peer *will* fuck it up, and that
fuckup might only be discoverable when you look at the interaction of
several different programs supplied by several different vendors and
written years apart.

--Andy