Socket activation for well-known locations

Hi all,

When developing mir-kiosk and everything around it we’ve found that there’s no way to encode service dependencies across snaps (mir-kiosk needs to start before any app tries to connect to it). Socket activation was suggested as a way to approach this, however the wayland protocol defines the socket to live in $XDG_RUNTIME_DIR, and snapd’s wayland interface puts it in /run/user/$UID/. However, when trying to create a service with /run/user/0/wayland-0 activation, the store rejects it with:

listen-stream '/run/user/0/wayland-0' filesystem paths does not start with $SNAP_DATA/... or $SNAP_COMMON/... lint-snap-v2_sockets_listen_stream (mir-kiosk, wayland)

Should this be something that gets manually accepted in the store? I can see that otherwise it might be a way to “escape” the confinement, but should this be a plain reject on the store, or rather a trigger for manual reviews?

@Saviq accepting in the store wouldn’t be enough. snapd rejects it when installed locally:

$ snap install --dangerous --devmode ./mir-kiosk_0.26.3+16.04.20170605_arm64.snap 
error: cannot read snap file: socket "wayland" has invalid "listen-stream": only $SNAP_DATA and
       $SNAP_COMMON prefixes are allowed

With a different goal in mind (namely D-Bus activated services), I put together the following PR:

https://github.com/snapcore/snapd/pull/5822

This allows snaps to provide user session daemons, including socket activated user daemons.

As is, the PR does allow snaps to listen on sockets in $XDG_RUNTIME_DIR, but it is in the snap’s private runtime dir (i.e. /run/user/$pid/snap.whatever/wayland-0).

Maybe this could be adapted for what you want to do?

@jamesh yes, as-is it doesn’t help - like you say it deals with the snap’s private runtime dir.

Connecting up Wayland snaps is awkward as things stand: the client and server both expect wayland-0 to be in $XDG_RUNTIME_DIR which has to be the same location (or contain a wayland-0 link that resolves to the same file).

The “wayland” interface allows the server to create /run/user/0/wayland-0 and the client to access it. What it doesn’t allow is socket activation.

You’re suggesting that we propose something along the lines of your PR that tests for the “wayland” interface? Or something more general?

I coded the PR as is to allow socket creation in places that the snap has write access to.

It also relies on the a user mode systemd instance, and I’m not sure how well that fits into what you’re doing. It is probably possible to set up this instance on an Ubuntu Core system with systemctl start user@${uid}.service, but it likely isn’t well tested at the moment (for instance the spread test in my PR fails on core due to some missing writable locations).

I suspect extending it to “special” locations has the same problem as for system daemons: the code generating the systemd unit wrappers is not tied to interface connection, so it’d be hard to base decisions on that data.