Re: kdbus: to merge or not to merge?

From: Andy Lutomirski
Date: Wed Jun 24 2015 - 15:44:16 EST


On Wed, Jun 24, 2015 at 10:11 AM, Alexander Larsson
<alexander.larsson@xxxxxxxxx> wrote:
> On Wed, Jun 24, 2015 at 5:38 PM, Andy Lutomirski <luto@xxxxxxxxxxxxxx> wrote:
>> Was this intentionally off-list?
>
> Nah, that was a mistake, adding back the list.
>
>> On Wed, Jun 24, 2015 at 8:10 AM, Alexander Larsson
>
>>> The way i did it in the userspace proxy is to allow peer exited
>>> messages from services that talked to you at some point, as this is
>>> the core requirement (you must be able to limit things to the lifetime
>>> of clients). However, i can see how tracking that in the kernel is a
>>> bit painful, so just allowing all is probably a reasonable choice.
>>>
>>
>> Hmm. I guess this is an ugliness of dbus in general. Since dbus
>> doesn't really have a concept of objects (AIUI) you can't really get a
>> notification that a particular object that you have a reference to is
>> gone, so you have to ask for notification that the peer providing the
>> object is gone, but there was never any concept of having a reference
>> to a peer, so here we are :(
>
> You keep using works like ugly and stupid, which isn't super
> impressive.

Fair enough. On the other hand, I've called my own code ugly plenty of times.

> My name is on the dbus specification, and I am (and was
> then) well aware of systems with object references. In fact, both
> previous ipc systems (Corba ORBs) that Gnome used before we designed
> dbus uses object references, and they had a lot of problems which dbus
> solved for us. I'm not saying dbus is perfect, but it has its reasons
> for the way it works.
>
> So, dbus-the-system has some kind of notion of an object reference
> (peer + object path), but the *bus* is fundamentally a way to
> communicate between peers, and the object path is merely some
> uninterpreted metadata.

I'm talking about the reference part, not the object part. Peer +
object path is a name, not a reference.

> Once the message reaches the destination
> process it is essentially free to interpret the object path however
> they want. If something needs a long lasting "reference" to an object
> you can implement that by e.g. using a Subscribe method, and you can
> guarantee cleanup because the bus will tell you if the peer died.

Except you can't pass them around. So it's still reference-by-name
instead of reference-by-actual-reference.

>
> This also means that the bus itself is vastly simplified. It only has
> to track peers, not every object in every peer. And clients are more
> flexible with how objects are handled. They can be instantiated
> lazily, or even created algorithmically from the object path if
> needed.

True. Nonetheless, things like Cap'n Proto and seL4 are quite simple
and have real references.

>
> You wish that the kernel controlled access to a particular object in a
> peer, but once the message is dispatched into the target process all
> bets are off anyway. It will be running some code parsing your message
> in the process with no real separation from the other objects. Any bug
> there could give you wider access. I don't see how this fundamentally
> makes the whole system much more secure. On the other hand, I *do*
> remember having to track down cross-process leaks from circular
> references between processes using Corba...

If you have peer ids keeping things alive on dbus, surely you can also
have circular references, no?

>
>>> The desktop file lists the icon, name and whatnot which is displayed
>>> by the desktop environment. If DBusActivatable is true, then the app
>>> is started by sending dbus messages to the same name as the desktop
>>> file, to the org.freedesktop.Application interface, this way we can
>>> ensure a singleton app and you can do more things than just spawning
>>> it.
>>
>> How do I install apps as an unprivileged user? What about running
>> sandboxed apps that aren't installed at all? What about downloading
>> one app and running three instances of it that are all isolated from
>> each other?
>
> Users install desktop files in a file in their home directory
> (~/.local/share/applications/ typically).
>
> xdg-app apps require some form of installation before running.

IMO that's unfortunate. If nothing else, it prevents programs from
easily starting one-off sandboxed apps that weren't separately
installed.

>
> You can run three instances of an app, but only one of them can own
> the bus name. This works out fine if your app does not use dbus, but
> it may be a problem if it uses dbus activation.

I'd really like to be able to xdg-app --stateless oowriter
some_untrusted_file.docx and have it fully functional, including
printing, even if I have another instance running.

>
>>> Well, your "other than" part kinda breaks things like launching the
>>> application. So, we need to be on the real bus.
>>> Could you then *also* have a bus per app for talking to the portal? I
>>> guess so, but I don't quite see the point. Just having the portals
>>> trying to find all new buses that come and go will be all kinds of
>>> painful.
>>
>> How many portals will there be? It seems like, if you want multiple
>> portals programs (in the org.freedesktop.portal.* sense), then you'd
>> have some awkwardness if each app were on its own bus and you didn't
>> want a proxy, but I think you'll also have prevented yourself from
>> meaningfully sandboxing the portals themselves.
>
> You can sandbox the portals to some extent, but fundamentally they are
> meant to run in some kind of "higher privileges" mode, so they have to
> have access to things normal apps would not. For instance, they have
> to be able to activate other dbus names.
>
>> Android, on the other hand, sandboxes most of its service providers,
>> and Binder provides a nice way to selectively grant capabilities
>> between sandboxes. (The privacy and security disaster that's built on
>> top of Binder is another story, but that's not Binder's fault.)
>
> Well, the service providers are not the same as the portals. Say you
> have a twitter client that you want to register to be able to share
> some selected text. The twitter client can be fully sandboxed. The
> portal is just the link between the requesting app and the list of
> registered share providers.
>

Ah. I clearly am misunderstanding something. What's a portal?

>> For launching the application, couldn't you just say "hey, portal,
>> launch this application please?" Using custom endpoints with shared
>> namespaces just for this purpose sounds unnecessary.
>
> Well, that is essentially what a portal like the share one does.
> Although it shows a user controlled UI inbetween to avoid the app
> being able to start any other app it wants.

Hmm. So shouldn't xdg-app be explicitly choosing which portals are
allowed for which sandboxed apps rather than allowing
org.freedesktop.portal.*?

>
>> Semi-shameless plug [1]: Sandstorm is inventing something quite
>> similar to what you're doing, but they're doing it with a single proxy
>> per sandbox instance and a capability model. There are no special
>> portal services -- instead, there's a general and *very* clean
>> mechanism for allowing other sandboxed applications to supply
>> interfaces that can be requested from any sandbox (with appropriate
>> user confirmation). It could be worth comparing notes. I'll try to
>> see if they have a nice summary of how the pieces fit together.
>
> That sounds similar to the portal idea, would be cool to read about.
>
>>> I don't think that is really a problem. People can do stupid things on
>>> the non-sandboxed side in all kinds of ways. You just can't protect
>>> against that.
>>
>> But you can prevent people on the non-sandboxed side from being
>> invoked *at all* from the sandbox without explicit user opt-in, which
>> makes the scope for screwing things up much smaller. If you combine
>> that with sandboxing the portal providers too, you end up in decent
>> shape.
>
> The non-sandboxed side can scribble all over your application. Trying
> to protect against it doing something wrong is imho fruitless.

Other way around. Vendors can and will write blatantly and perhaps
intentionally insecure things. If they can expose them via
org.freedesktop.portal.* so their little widget is easier to
implement, they will. If it has to go through a sharing mechanism,
then it will at least only be accessible to apps that the user has
explicitly granted access to.

>
>>> Basically, the app id is linked to the dbus names that the app may
>>> own. So, the only way it could take over org.gnome.gedit is if you
>>> actually install the app called "org.gnome.gedit". Of course if you
>>> trust some random untrusted repo and install something called that you
>>> get what you want...
>>
>> Um.
>>
>> Have you ever noticed that friendly android app names like "Yelp" have
>> nothing whatsoever to do with the app ids? Heck, it's hard to find an
>> app id shown in the UI at all when installing an Android app.
>> Nevertheless, you're supposed to be safe if you install random apps,
>> as long as you don't grant them dangerous permissions.
>>
>> So, yes, users really ought to be protected against apps that
>> partially break the sandbox because their names are malicious.
>
> Yeah. I'm aware of this. Anything that allows free text and icon to
> describe the app will be able to impersonate another app (to the user,
> if not the system). The only solution to this is manual verification
> and trust. The limitations above make it possible for a reviewer to
> check the app id and the exported files (such as the desktop file and
> the dbus service file) and will be able to catch such impersonation.
> So, if you trust an upstream to do such verifications you register
> their public gpg key for the repo.

Or you could design the system such that the name of the app simply
does not matter. An app with the same name and icon can, of course,
impersonate the app to the user, but it's in a sandbox so the damage
should be limited. Allowing an app with the same
not.shown.dotted.name to cause damage seems like a design flaw.

>
> That obviously doesn't scale super well, as you don't want every user
> to have to trust every upstream. So, what I want to do is have
> repositories that only have references to other repositories + local
> signatures. That way e.g. gnome could run an app store, which
> essentially collects a set of upstream repositories, does some manual
> verification of each new release and then slaps a signature on it. The
> user could them chose to trust this middle-man instead of each
> individual upstream. This is basically how android solves this. They
> have people looking at submitted apps. Only with this approach you are
> not tied to the google appstore only. The whole system is distributed.

It would be nice to avoid having to trust the repository at all,
except perhaps to the extent that if you're downloading a "Yelp" app,
then perhaps you'd have to trust it enough that you believe it's the
Yelp app when you type your Yelp password in to it.

>
> You're free to design such a system and write a desktop to use it.
> However, in Gnome (and in the other desktops as well), dbus is already
> used for all ipc like this and all the freedesktop specs,
> infrastructure, type systems, interfaces, code and frameworks are
> built around that. There has to be a *massive* advantage for us to use
> something else, and I'm not at all convinced by the issues you bring
> up.

The custom endpoint policy thing is brand new, whereas using a
userspace proxy for xdg-app actually sounds easier than using a
separate kdbus bus. Sticking dbus in the kernel would also be new.

--
Andy Lutomirski
AMA Capital Management, LLC
--
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/