Interface connections in multi-user systems

Currently snaps are connected to eachother using a global interface connections (i.e. plugs and slots). For example to connect the vlc snap to the camera you do the following:

$ snap connect vlc:camera :camera

Once this is done then any user using VLC on this system now has access to the camera. In the future, this is likely to be done using an graphical access prompt shown to the user when they attempt to use camera access.

This is a problem because another user on the system would now have VLC (or a more malicious application) able to record them without ever being prompted. I would expect the second user to have not have this interface connected when they first use the application.

This suggests there need to be per-user connections, however there are also system level connections for things like daemons. I’m not sure technically how snapd juggles these two requirements.

1 Like

Making interface connections per-user would require a lot of other things to become per-user (AppArmor profiles, mount namespaces, etc). It also adds complications around how different components of a snap running as different users should be able to communicate (e.g. a system daemon with a client app running as the user).

I also leaves us with the problem of the user lacking context for the decision: if I’ve downloaded a package purporting to be VLC, it would be nice if I only had to grant access to the camera when/if I decide to use that feature of the app. If I’m just watching a video and get asked for camera access, I might decide that something fishy is going on.

For Ubuntu Phone, we had trusted helpers for this kind of thing: the security policies gave apps access to the trusted helper and then the trusted helper would make a decision about granting access, and possibly save the decision. That kind of set up avoids the need for adapting AppArmor profiles on a per-user basis.

Note that on Touch the devices were assumed to be single user, so we were never faced with this. Also-- multi-user interface connections are not an existing requirement. Currently (pre-gnome-software support for interface connections), it is pretty clear that the install and interface connections are system wide since the snap command needs to be run by an admin (either via sudo or after obtaining a macaroon). gnome-software blurs that line a bit, but I think if we have the mental model that these are system wide operations (install, connect, remove) and present this clearly (and otherwise document it), we should be ok.

Importantly, it isn’t just AppArmor: there is seccomp, device cgroups, kmod backend and mount namespaces that are all influenced by interface connections. AppArmor and seccomp are arguably the easiest to imagine a fix to support this: simply tack on the uid to the profile names and have snap-confine DTRT to pick the right profile. But this is too simplistic due to daemons (as mentioned by others) but also the device cgroups, mount namespaces and kmod. Interface connections can reach out to the system in many different ways. IME, the only way to support this would really be to have per-user installs of snaps so that all the backends everything is completely separate so that the ‘snap ID’ concept (ie, snap.$SNAP.$COMMAND) is extended to include the uid (but again, daemons are problematic here).

We can definitely explore the idea of per-user connections, but there’s no strong requirement to do that right now as in most cases systems are owned by a single person or a single administration team, and we have much more interesting features in our short term roadmap to nail down, so this idea will have to wait a bit.