Evaluating privilege separation for postmarketOS and Alpine apps
Hey all, I've had a busy week and then unexpectedly also a busy weekend. So I wasn't able to do the backlog there as planned. Sorry for that, I'll go through it as soon as I find time. Here is an issue that I prepared all week, I'd like to at least share that with you. Cheers!
The next immediate goals are basing on Alpine stable (#11 (closed)), getting at least the Pinephone fully supported (#3 (closed)), categorizing devices better (#13 (closed)). But another important topic, that we should tackle after that (or even in parallel if somebody not involved with the above three tasks finds time), is "proper support" for apps:
- touch friendly GUI applications
- easy to install
- privilege separation (only has access to what it needs, i.e. a PDF reader only needs read access to everything except for configs and should not need network access)
An "app store" for postmarketOS should not list programs that would not be accepted in postmarketOS or Alpine. Especially:
- proprietary apps
- apps that track users
- apps that display advertisements
Nowadays we have some apps, but they are not easy to install yet (only with apk on the command-line), and they don't have privilege separation.
I have put Alpine in the title, because after careful evaluation I would like to arrive at a solution that we could reasonably propose to Alpine, and after approval, submit patches to upstream it to Alpine.
Flatpak
Honestly I had already discarded flatpak earlier (postmarketos.org#94). But this week I've seriously considered it again. After all, flatpak is already in Alpine and we have a nice gui with Discover.
The official repository, flathub, has all sorts of proprietary applications like skype. We can't use that, so we would need to roll our own git repository for flatpak manifests (the recipies like APKBUILDs) and host our own flatpak repository. For all "SDKs" and for all apps, so we make sure that we build everything from source.
I don't think this is good for postmarketOS, because it would immensely increase the maintenance effort. Let's illustrate this with evince APKBUILD and flatpak manifest. Note that each app only depends on a "SDK" (org.gnome.Sdk in this case), all other dependencies are built from source and shipped with the app.
- essentially we get a second pmaports repository that works entirely different
- existing tooling (pmbootstrap, CI) can't be used
- increased RAM usage, since libraries are loaded multiple times when using apps, the version from Alpine/pmOS apk and at least one flatpak version
- updating a library suddenly means touching the flatpak manifests of all apps using that library, which is much more effort. Deploying security fixes for libraries would be a nightmare.
My recommendation is, that we make it easy to use flatpak for people who really want to (https://gitlab.com/postmarketOS/pmaports/-/issues/491) but do not recommend or support it. Then people can use flathub or purism's upcoming flatpak repository (hopefully only of free software mobile friendly applications?) if they like and we avoid the maintenance burden.
Minimalist alternative: privsep subpackage
I propse that we create privsep
subpackages for each app package, that we
care about. Have it install a privsep.sh
in /usr/privsep/bin/$pkgname
, if
the package was installed and privsep-base
is installed in the system:
subpackages="... $pkgname-privsep"
source="... privsep.sh"
# ...
privsep() {
install_if="$pkgname privsep-base"
install -Dm755 "$srcdir"/privsep.sh "$subpkgdir"/usr/privsep/bin/$pkgname
}
The privsep.sh
would look like this (based on example):
#!/bin/sh
exec bwrap --ro-bind /usr /usr \
--dir /tmp \
--dir /var \
... \
/usr/bin/path-to-real-application
privsep-base
would depend on bubblewrap
and provide a profile script, which
places /usr/privsep/bin
at the beginning of $PATH
. Bubblewrap
is a lightweight program that flatpak is using internally for privilege
separation. (We should even be able to run flatpak with some verbose parameter
to make it display the bwrap command it generates.)
In my opinion, this nicely integrates with the APKBUILDs postmarketOS and Alpine already have. The whole thing is optional. I don't care so much about locking down the applications perfectly with every seccomp rule we can apply, I would rather shoot for some basic privilege separation, like stripping internet access for all apps that don't need it. That way it should not break on updates while still having a day and night difference in security compared to how it is now. Also it should hopefully work with most downstream kernels too.
Please note that I have not tested the above approach. Help with creating a proof of concept is welcome and this would be the next step if we decide to go with this solution.
What about portals?
Portals are a mechanism to make an unprivileged app ask for permissions, e.g.
to let a pdf reader display a file open dialog that has access to everything
owned by your user instead of only having access to what the pdf reader is
allowed to read. AFAIU flatpak does this with a daemon listening for dbus
requests for such portals from the bubblewrapped apps, then forwards the chosen
file to the sandbox (also via dbus?) or performs whatever other action the
portal is supposed to do. It should be possible that we build the same
mechanism, and re-use flatpak's daemon somehow. To let GTK apps request portals
for file open dialogs, one apparently only needs to set
export GTK_USE_PORTAL=1
(which the privsep.sh would do in the bwrap call).
Again, if somebody could help with building a proof of concept, it would be greatly appreciated.
What about an "app shop" gui?
@minlexx is already working on apk support for Discover. Besides that, we would need some way to mark some apks as "apps" and add a nice description, icon and screenshot that would then be displayed in Discover. AFAIK there is the appstream format for that exact purpose, and it is also supported in Discover.
I image that we would have an extra repository for these appstream files, pmapps.git, and it would have one dir for each app, with the metadata. In contrary to having our own flatpak repo, this would not duplicate stuff from the pmaports repository so it should be a lot easier to maintain.
@minlexx: does this make sense?
What about rollbacks of app updates?
Unlike flatpak, the privsep subpackage approach does not make it possible to roll back apps conveniently after an upgrade went wrong. Because updating an app may have updated depending libraries at the same time, and other programs may depend on the new library.
But I argue that this is not something we should optimize for. I propose a rollback of the whole (package manager maintained) system with btrfs and snapshots. Snapper seems to be the appropriate tool, and it is packaged in Alpine. I have not tested it personally.
Details in https://gitlab.com/postmarketOS/pmaports/-/issues/492
What about snap?
Well, I did not only look into flatpak, but also a bit into snap. It uses Apparmor for privilege separation, and Ubuntu Touch has their own app repository: https://open-store.io/
Maybe there would be a chance for collaboration... I have not looked into the technical details, but I don't think we could get around all the issues I have listed for flatpak from postmarketOS perspective and result in an as minimalistic solution that could possibly be upstreamed to Alpine. Feel free to convince me otherwise, though.
Conclusion
So... I propose my minimalistic approach listed above. Thanks for reading, looking forward to feedback and help with proof of concepts!