Hello:
This message was originally posted to chromium-dev, and I was referred here due to the involvement of sandboxing in this proposal. If the message seems familiar to you, that's likely why.
For starters, in case anyone here isn't familiar with the idea:
Flatpak is a sandboxed application distribution platform for Linux. All apps are stored inside an OSTree repo (like Git for binary files), and applications are run inside runtimes that are isolated from the host.
Flatpak's sandbox allows syscalls such as BPF (this is interesting for reasons that will be clear later), but it disallows setuid binaries and unshare calls. This, of course, becomes a bit of a problem for Chromium's sandbox. However, Flatpak *does* include something else that we can use: flatpak-spawn.
flatpak-spawn is a binary that calls into a D-Bus API, and this D-Bus API allows you to start new process in a new user and PID namespace parallel to the current one. flatpak-spawn --sandbox is also available, which performs a similar task but drops all permissions in the process. For instance, flatpak-spawn ls $HOME would be running in a separate namespace to Chrome but still can access $HOME, whereas with flatpak-spawn --sandbox, $HOME would appear entirely empty.
This works by using flatpak-spawn --sandbox to launch child processes, that way they're sandboxed from the host.
In its current state, there are a few known issues:
- I sadly had to disable use of the Zygote for now. The zygote host expects to be able to control processes inside of the zygote's PID namespace, such as killing them and monitoring their status. However, since flatpak-spawn always runs in a PID namespace *parallel* to the current one (in contrast to the namespace sandbox running in a PID namespace beneath the current one), the zygote host cannot see any of the processes inside the zygote's namespace. This means that it would receive invalid PIDs and still try to control and kill the processes, which often led to it...killing itself instead.
From what I can tell, the only main way to fix this would be for the zygote itself to be responsible to reading the status of and killing processes; the zygote host could send a pickled message to the zygote with a command request. I am partly mentioning this here to ask if a solution like this would be approved, or if there is a particular reason that the zygote could not be responsible for managing its peers. (If the zygote itself had to be killed, the host could still kill the flatpak-spawn process, which in turn would result in any inside its sandbox to be killed.)
- Due to unshare being blocked, Zygote-forked processes cannot move themselves to a separate PID namespace. At a glance, it seemed that only the namespace sandbox did this (the setuid sandbox simply drops all credentials), and it is also important to note that Chromium's BPF sandbox also still is fully functional, as well as Flatpak's own restrictive BPF sandbox.
- The GPU process currently runs via normal flatpak-spawn (which has filesystem access), not flatpak-spawn --sandbox. The latter drops all permissions, including the ability to access the X11 display, therefore the GPU process dies immediately. Again, it is worth noting that Chrome's BPF sandbox still applies, so once it is entered, all filesystem access results in EPERM (also note the next point).
- The only reason Chrome requires full filesystem access right now is because it cannot use the XDG filesystem portal. The XDG filesystem portal provides a D-Bus API that an application can call into in order to open a file chooser dialog box; the files chosen are decided by the portal and selectively exposed into the Flatpak sandbox via the documents portal (a FUSE filesystem that mounts the files). There is an open issue for this that I will likely look into solving:
https://bugs.chromium.org/p/chromium/issues/detail?id=885292
Despite all this, the XDG filesystem portal does *not* currently allow opening directories for security reasons. This is tracked via
flatpak/xdg-desktop-portal#200, and I have written a proposal for support for this via a scoped storage-like API at
flatpak/xdg-desktop-portal#334. As far as I can tell, the only access that requires this would be adding new developer extensions.
As a side note, the XDG config, cache, and data directories (normally ~/.config, ~/.cache, and ~/.local/share) are set to application-private directories and available without filesystem access as well. (flatpak-spawn --sandbox processes cannot access them, however.) They are all placed under ~/.var/app/com.google.Chromium; no Flatpak apps cannot access the XDG directories of other Flatpak apps without special permissions (not even normal filesystem access allows this).
- Messages that look like this randomly appear, which usually results in a process or new tab page crashing:
ldconfig: Changing access rights of /run/ld-so-cache-dir/baa04b8f378d418299a60f7a29ab3c82b55d79085c57e4b0c6684252705fefaa~ to 0644 failed: No such file or directory
- Right now, checking if Chromium is inside the Flatpak sandbox requires a blocking operation: checking if /.flatpak-info exists and opening it. Therefore, a base::ScopedAllowBlocking instance was temporarily added to work around this until a cleaner solution is arrived upon. It is worth noting, however, that this file is managed my Flatpak and should be available almost instantly.
- I am aware that the sources I linked above require a separate Python script to build Flatpak bundles, in contrast to the normal installer integration with the GN build system. This is just temporary in favor of getting an initial build out quickly and will be changed later on.
- I did not focus particularly on NaCL's sandbox, since that has been deprecated on Linux anyway and most recently seems to have been potentially removed.
flatpak install com.google.Chromium
Flatpak does have one-click systems for adding remotes and installing apps (via .flatpakrepo and .flatpakref files), but, again in favor of getting an initial build out quickly, I have not created those files yet. With them, you can simply download and then double-click the file, and the distro's software center will open to either add the remote or download the app.
Although Flatpak does have a build environment, these builds still use the sysroot, since I had trouble making the unbundle scripts and non-sysroot build work with goma and RBE at the moment.
This work would also hold potential benefit to Google; Flatpak is a cross-distro packaging system that would allow for easier distribution of new Chrome builds. It is also worth noting that, unlike some other, similar technologies, Flatpak does allow for multiple remote repositories to be added. This means that any distribution could be controlled by Google and would not have to go on a centralized store of any kind. flatpak-builder even handles stripping debug info and moving it into a separate extension.
Therefore, I am posting this here partly to gauge any potential interest for this upstream, as well as to make sure there aren't any particularly negative consequences of the approach I'm planning to take (barring the known issues mentioned above of course).