Make tails-persistence-setup compatible with Wayland
#7 Updated by intrigeri 2019-09-08 14:29:05
So, we’ll need a privileged backend that:
- runs as the t-p-s user so it is allowed to:
- do the necessary udisks operations (source:config/chroot_local-includes/etc/polkit-1/localauthority/10-vendor.d/org.boum.tails.pkla)
- run the
/usr/bin/tails-fix-persistent-volume-permissionscommand as root (source:config/chroot_local-includes/etc/sudoers.d/zzz_persistence-setup)
- exposes an API that can be used by a CLI and GUI running as the amnesia user (and possibly, some day, the
Debian-gdmuser, if we ever want to integrate creating the persistence in the Greeter)
- this looks like a job for a D-Bus service listening on the system bus
- only the amnesia user must be allowed to used that API; this looks like a job for PolicyKit
The API exposed by the privileged backend should only offer operations that the amnesia user can already perform. This set of operations is currently limited by a combination of:
- The only way the amnesia user can escalate its privileges to the t-p-s user’s is via sudo t-p-s.
- The amnesia user can only pass a small set of options to t-p-s via sudo (source:config/chroot_local-includes/etc/sudoers.d/zzz_persistence-setup).
- The t-p-s CLI and GUI restrict what the user can do as the t-p-s user. For example, the t-p-s user has full read/write access to the persistence configuration file, but the t-p-s CLI and GUI don’t expose that much flexibility to their user.
If we’re lucky, a well-designed API + PolicyKit rules will give us, without any extra work, the same security properties. That is, ideally an adversary who gets access to the D-Bus system bus as the amnesia user + arbitrary code execution as the amnesia user should not be allowed to do anything that they can’t currently do with the same privileges (which includes, unfortunately: everything they can do by remote controlling the t-p-s GUI via X11).
If we’ve very lucky, the overall security will even be better.
But if we’re unlucky, the possibilities offered by said API + PolicyKit rules will necessary make things worse than the current situation, unless we add some more restrictions. Given we’ll be in similar situations for the Upgrader and the Unsafe Browser, I’ve thought a bit about what we could do if we have this problem.
- The first option boils down to using technologies that were created for sandboxing, in order to do the opposite, that is: grant elevated privileges to one specific program. In the case at hand, we could for example only allow the new CLI and GUI to connect to the D-Bus service (as opposed to any process running as the amnesia user):
- Under Wayland, this sort of restrictions becomes meaningful: an adversary cannot remote control the GUI via X11 tricks. Except there’s still the accessibility bus problem, which may make this entire hypothesis moot. The CLI is a problem but that can surely be solved, somehow.
- In theory, AppArmor could be used for this (https://dbus.freedesktop.org/doc/dbus-daemon.1.html) but:
- The necessary support is not in Linux mainline yet.
- It’s better suited to restrict D-Bus access of all confined apps, than to elevate access of one specific app: non-confined apps could still access the D-Bus service, so we would need to use
pam_apparmoror similar to ensure all processes run as the amnesia user run under some AppArmor profile that does not allow full D-Bus access. This seems hard and risky.
- xdg-dbus-proxy could be useful here. That’s what Flatpak uses. In our case, we would not give the amnesia user access to the D-Bus service. Instead, we would have a privileged setuid wrapper around the t-p-s GUI, that runs xdg-dbus-proxy as a dedicated user who’s allowed to access the API, sets up a filesystem namespace that contains the socket created by xdg-dbus-proxy (bubblewrap seems ideal for this), gives read/write access to the amnesia user on this socket, and finally runs the new t-p-s GUI as the amnesia user in that namespace. There may be existing code that does all that (note to myself: ask smcv). Recent webkit2gtk uses both bubblewrap and xdg-dbus-proxy so its code base might have the solution.
- The second option is to require the user to confirm the most dangerous operations, in a way that cannot be done by the adversary. This sounds like a job for PolKit + GNOME Shell. If done carefully, there’s a chance it does not make UX much worse. It’s likely vastly easier than the first option.
Anyway, hopefully we’ll be lucky, the simplest thing will work, and we won’t need to go explore this space that far here :) I’m pretty sure we will need to for the Upgrader though.