Containers (#171): Work out what to do about unrestricted connections
Originally fdo#103458, older comments will be more readable there.
User story
dbus maintainers want a plan for how Flatpak is going to represent unrestricted connections and whether they are going to have any restrictions at the D-Bus level, so that we can avoid painting ourselves into a corner.
Description
Flatpak has the concept of unrestricted connections to the session and system buses, selected by --socket=session-bus, --socket=system-bus. These bind-mount the session or system bus socket directly into the container if possible (or use xdg-dbus-proxy in pass-through mode if the socket is abstract), without interposing xdg-dbus-proxy --filter
and its implicit restrictions on what the connection can do (such as forbidding UpdateActivationEnvironment()
).
These connections are effectively totally trusted - there are lots of ways an unrestricted connection to the session bus can execute arbitrary code outside the sandbox context (doing the equivalent of systemd-run --scope $your_payload_here
is an obvious one, and so is the o.fd.Flatpak.Development interface), and the same is probably true for the system bus. But we probably want to be able to identify these connections, even though we can't control them.
With the implementation in fdo#101354, there are some hard-coded things that such connections can never do:
-
Call methods with
METHOD_FLAG_PRIVILEGED
:DBus.UpdateActivationEnvironment()
(privilege escalation via LD_PRELOAD etc.),DBus.BecomeMonitor()
(privileged information leak) -
Call methods with
METHOD_FLAG_NO_CONTAINERS
:Containers1.AddServer()
(privilege escalation via specifying weaker access control, identity spoofing by specifying a different identity for the server)Containers1.{StopInstance,StopListening}()
(denial of service), the wholeVerbose
interface (indirect information leak, denial of service because Verbose is really really spammy), the wholeStats
interface (minor information leak) -
Add match rules that enable eavesdropping (privileged information leak)
-
Report that systemd activation has failed (denial of service)
-
Probably more in future
I'm not sure whether a contained app will ever do these in practice. I could imagine GNOME Builder wanting to BecomeMonitor()
or use Verbose or Stats, although at the moment it just uses --talk-name=org.freedesktop.Flatpak
to escalate its privileges, rather than having a totally unrestricted socket.
Options include:
-
Deny some or all of this on filtered connections (#185), let container managers allow it by adding extra allow rules, and maybe allow it on unfiltered connections (until #185, that's all connections) to preserve the invariant that not specifying filtering means allowing everything that can possibly be allowed; but that would mean that #185 would become part of the minimum viable product for #171, which is undesirable, because #185 will never be finished unless someone else helps.
-
Unconditionally forbid this stuff on the assumption that nobody will ever need it (This is @smcv's plan if there are no strong objections.)
-
Either now, or later (if we unconditionally forbade it but we turned out to be wrong about never needing it), have a flag in the
a{sv}
of named arguments that relaxes our access control for a particular container instance (maybe{'AllowMonitoring': <true>}
etc.?), and relax some of the restrictions in that situation. (This is @smcv's fallback plan if 2. turns out to have been wrong.)
If we might let containers do privileged things in future, we might want to change the semantics of M_F_PRIVILEGED
so that it's orthogonal to M_F_NO_CONTAINERS
(in fdo#101354, M_F_NO_CONTAINERS
was strictly weaker than M_F_PRIVILEGED
); or, alternatively, we might want to add a M_F_PRIVILEGED_UID
that is really orthogonal to M_F_NO_CONTAINERS
, which would make M_F_PRIVILEGED
equivalent to M_F_PRIVILEGED_UID|M_F_NO_CONTAINERS
.
Deadline
If there is no objection to this by the end of September 2023, when Containers is otherwise ready for merge, @smcv plans to go with option 2 and close this with no further action. We can still take option 3 later, if we need it.