New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interfaces: support D-Bus activation #6258

Open
wants to merge 17 commits into
base: master
from

Conversation

Projects
None yet
4 participants
@jhenstridge
Contributor

jhenstridge commented Dec 4, 2018

This is a reworking of PR #2592, expanded to work for both system and session services. In addition to that generalisation, I've made a few changes to how things are handled:

  1. The service activation files are now named after the bus names rather than snap names. This is required for system bus services, but it had the side effect of making it a lot easier to check for existing name ownership.

  2. I renamed the new interface attribute from service to activatable. This was a suggested change on the old PR.

  3. If the app associated with a dbus interface slot is a daemon, we add a SystemdService key to the service activation file, which causes the daemon to be launched via systemd. This currently only benefits system services, but it will be easy to generalise it to session services with PR #5822.

I do wonder whether it would make sense to limit activatable services to "daemons" and not "apps". Given that the snap needs to ask for activation support, there is no backward compatibility issue.

I'm still working through getting the spread tests ported forward, which is why I've marked this WIP.

@jhenstridge jhenstridge force-pushed the jhenstridge:dbus-activation branch from 094458f to 28e83b3 Dec 4, 2018

Show resolved Hide resolved interfaces/builtin/dbus.go Outdated

@jhenstridge jhenstridge force-pushed the jhenstridge:dbus-activation branch 3 times, most recently from 1bd1a83 to a5a59f7 Dec 5, 2018

@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 6, 2018

This branch relies on changes to the test-snapd-dbus-service snap. Those changes have been merged to the bzr branch and the build recipe has run, but I think they're either stuck in manual review, or need manual review requested:

https://launchpad.net/~mvo/+snap/test-snapd-dbus-service

I can't see the dashboard for the snap.

@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 8, 2018

I've run into a few problems trying to get my spread tests running on Ubuntu 14.04. I get the following from the dbus-activation-system test:

+ echo 'Making a method call wakes the service'
Making a method call wakes the service
+ MATCH hello
+ dbus-send --system --print-reply --dest=io.snapcraft.SnapDbusService /io/snapcraft/SnapDbusService io.snapcraft.ExampleInterface.ExampleMethod
Error org.freedesktop.DBus.Error.Spawn.FailedToSetup: Failed to setup environment correctly
error: pattern not found, got:
-----
.

On 14.04, the system bus is run by Upstart so it is starting the service manually via the Exec line in the .service file rather than asking systemd to start the service. This is done via the dbus-daemon-launch-helper process, which is passed a D-Bus service name. It uses a simplified config file parser that seems to ignore include directives, so doesn't find service files I'm stashing in /var/lib/snapd/dbus/system-services.

[note that session services work fine, since it doesn't use dbus-daemon-launch-helper to start them].

I suspect the same will happen on newer distros for system services presented as "apps" rather than "daemons" in snap.yaml. There are two ways I can see forward:

  1. Consider 14.04 a lost cause. We are 4 months away from it's end of life after all.
  2. Refactor the code to put service files in /usr/share/dbus-1/system-services along with non-snapd services. This would likely require making the directories writeable on Ubuntu Core systems, and I'm not sure what effect it would have on upgrades.

@jhenstridge jhenstridge changed the title from WIP: interfaces: support D-Bus activation to interfaces: support D-Bus activation Dec 10, 2018

@jhenstridge jhenstridge force-pushed the jhenstridge:dbus-activation branch from 374fd55 to 5de375a Dec 10, 2018

jhenstridge and others added some commits Dec 3, 2018

interfaces/dbus: install conf files to point at D-Bus service activation
files in /var/lib/snapd.

Co-authored-by: Michael Vogt <mvo@ubuntu.com>
interfaces/dbus: add AddService method to dbus.Specification
Co-authored-by: Michael Vogt <mvo@ubuntu.com>
interfaces/builtin: add an "activatable" attribute to the dbus interface
When set to true, a D-Bus service activation file is installed for the app.

Co-authored-by: Michael Vogt <mvo@ubuntu.com>

@jhenstridge jhenstridge force-pushed the jhenstridge:dbus-activation branch from 5de375a to 990033d Dec 10, 2018

@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 10, 2018

There's currently a few failures in the spread tests:

2018-12-10 10:48:16 Failed tasks: 5
    - google:centos-7-64:tests/main/dbus-activation-system
    - google:ubuntu-14.04-64:tests/main/dbus-activation-system
    - google:ubuntu-core-16-64:tests/main/dbus-activation-system
    - google:ubuntu-core-18-64:tests/main/dbus-activation-system
2018-12-10 10:48:16 Failed project prepare: 4
    - google:opensuse-42.3-64:project
    - google:opensuse-42.3-64:project
    - google:opensuse-42.3-64:project
    - google:opensuse-42.3-64:project

It's not clear that the opensuse failures have anything to do with my branch: it looks like the Go compiler is being invoked with -std=something (a flag intended for gcc) and blowing up.

The ubuntu-14.04-64 failure is the one I mentioned in the previous comment: activating system services via dbus-daemon-launch-helper fails, and 14.04 does not configure the system bus to use systemd activation.

The ubuntu-core-16-64 failure is due to the test trying to talk to the dbus service from an unconfined context, which does not work on core systems. Updating the test to use a client snap with the interfaces connected should make it work on core+classic.

The ubuntu-core-18-64 failure is a ServiceUnknown error. I think the dbus-daemon config fragments I introduce in this PR aren't present on a core18 system. I'm not quite sure how it's meant to be exposed.

The centos-7-64 failure also reports ServiceUnknown. I'm not quite sure of the root cause here yet: there's no failure on Fedora or Amazon, which are using the same spec file.

@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 11, 2018

With the test modified to use a confined D-Bus client, I'm seeing failures on 18.04 and 18.10: when the service is inactive, the AppArmor rules block the method call before activation can occur. It's fine on 16.04, so I suspect there is something different in the kernel or dbus-daemon.

@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 11, 2018

From what I can tell, dbus-daemon passes an empty destination security label to the kernel when checking a method call to a not-yet-activated service. Manually adjusting the rule to

# allow connected snaps to io.snapcraft.SnapDbusService
dbus (receive, send)
    bus=session
    peer=(name=io.snapcraft.SnapDbusService, label="{snap.test-snapd-dbus-service.session,}"),

... seems to allow the client to activate the service. That doesn't seem to allow communication with unconfined peers, or activation of names other than the one specified in the rule. @jdstrand: can you think of any problems with this change to the rule?

interfaces: allow dbus plug to talk to service with blank security label
When the destination D-Bus service is not running, D-Bus will perform an
AppArmor check with a blank destination security label (since the
destination process doesn't exist yet).  This additional rule won't
match unconfined processes, or allow activation of other D-Bus names.
@jhenstridge

This comment has been minimized.

Contributor

jhenstridge commented Dec 12, 2018

With the changes to the AppArmor rule, we're down to two failures:

2018-12-12 05:18:01 Failed tasks: 2
    - google:ubuntu-14.04-64:tests/main/dbus-activation-system
    - google:ubuntu-core-18-64:tests/main/dbus-activation-system

The 14.04 failure is the dbus-daemon-launch-helper issue, and core-18 failure is due to missing the configuration needed to point at the service files I'm writing. Perhaps adding some symlinks to the core18 snap would be the most appropriate option.

I've got no idea why centos-7-64 is now working. I wouldn't have thought any of the changes I made would affect that.

@jdstrand

See previous comment for a way to assign a label to the activated service.

# to enable service activation
dbus (receive, send)
bus=###DBUS_BUS###
peer=(name=###DBUS_NAME###, label="{,}"),

This comment has been minimized.

@jdstrand

jdstrand Dec 12, 2018

Contributor

I believe this could be combined with the previous rule so there is one rule with peer=(name=###DBUS_NAME###, label="{,###SLOT_SECURITY_TAGS###}"),

That said, this continues to be annoying behavior from upstream that we never really cared for. This came up in #4495 for snapd. In that PR, we added to the .service file:

AssumedAppArmorLabel=unconfined

In that light, I'd prefer instead of the above rule change that when snapd generates the service file for the snap, for it to create:

AssumedAppArmorLabel=snap.NAME.COMMAND
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment