Socket activation support

@stgraber Ah, sorry, I misunderstood your proposal. You mean allowing only $SNAP_DATA and $SNAP_COMMON. Yeah, that sounds fine as a first step. The implementation I mentioned above is likely what we should aim for, as it enables other use cases, but we can do that as a follow up and it would remain compatible with what you suggest too.

Right, thatā€™s what I had in mind. Lets limit it to something we know is safe for now, then extend it later for more complex use cases.

@niemeyer should we disallow abstract unix sockets (as theyā€™re not confined IIUC)?

Yes, sounds like a good idea for now. We also need to get a review from @jdstrand before the final PR goes in, so he has a chance to pick up any other issues around that sort of problem.

Actually, abstract sockets are mediated. Like so many other things, it is a matter of namespacing. Abstract sockets often look like this: @foo, but they can have the form: @/path/foo. Iā€™m not saying the first iteration should support abstract sockets, but it could if the namespacing was right. Eg:

  • @snap.$SNAP_NAME.whatever (eg, @snap.foo.whatever)
  • @$SNAP_DATA/whatever (eg, @/var/snap/foo/x1/whatever)

Today, the default template does not allow creating abstract sockets, but this is only because we never decided on how to namespace them (it was discussed long ago, but never brought up again).

@jdstrand Not in this case, I suspect. Itā€™s systemd that is opening up the socket. We have the same issue described above about writing of unix sockets.

Well, unless we do enforce it at the namespacing level rather than hoping for apparmor to catch it.

To be clear, I was not talking about Linux namespaces/containers. We can carve out abstract socket ā€˜pathsā€™ that follow snappy conventions and enforce that with apparmor, in a similar fashion like we do now with the filesystem. We just have to decide how we want to carve that up (glossing over implementation details of making it work with systemd).

@niemeyer @jdstrand thanks for the clarification. Iā€™ll reject abstract sockets for now in the listen-stream validation.

Iā€™m also wondering what should be allowed in terms of TCP addresses; can we just limit to a port (which would be the same as allowing [::]:<port>) or should it be possible to specify addreses to (so that an app can, for example, bind only localhost)?

I donā€™t have an opinion on the actual question, but have a related question. You mention ā€œbind only localhostā€ (emphasis mine); aiui systemd is merely going to listen on these itself, start the application then hand over the fd to the service, but the service is free to open and listen on any number of other ports (or named sockets or abstract sockets) as is desired. As such, the ā€˜onlyā€™ here refers to the fact that the port will be open on the localhost, but not eth0. All of this is fine AFAIC. Fine-grained network mediation is on the roadmap, so at some point we will be able to enforce ā€œyou may only this port on this interface and no othersā€.

I ask because I want to make sure we donā€™t try to use ā€˜Socket Activated OS Containersā€™ (see http://0pointer.de/blog/projects/socket-activated-containers.html) since those wonā€™t work right with snapd.

Reading https://www.freedesktop.org/software/systemd/man/systemd.socket.html I see no reason why we could not include abstract sockets at this time. Like with named sockets, we simply limit their naming so different snaps canā€™t clobber each other. Eg, like I said before (feel free to suggest other ideas):

  • @snap.$SNAP_NAME.whatever (eg, @snap.foo.whatever)
  • @$SNAP_DATA/whatever (eg, @/var/snap/foo/x1/whatever)

snapd ensures the abstract sockets match our naming convention when generating the systemd unit and we add a couple of apparmor glob rules to the default template that allow unconfined to access the socket and for anything in the snap to access it. Anything beyond that is out of scope for this PR (but other snap access is obviously implemented via interfaces).

1 Like

If thatā€™s the case, I think @$SNAP_COMMON/whatever should be also supported (to match what would be allowed for filesystem-based unix sockets)