All exported regular files (not directories) need to have a filename
that starts with the application name, followed by either a dot or
any character that is invalid in an app name.
For instance, given an app name of org.gnome.gedit, these filenames
are exported:
org.gnome.gedit
org.gnome.gedit.png
org.gnome.gedit.plugin1.png
org.gnome.gedit-symbolic.svg (- is not a valid character)
However, these are not exported:
org.gnome.geditor
gedit.png
This has several advantages. First of all it ensures that there are no
conflicts between unrelated applications, secondly we also only allow
applications to install dbus services and desktop ids that are the
same as the app id, or sub-services of it.
Rather than keeping around a symlink to the temporary file we rename
the temporary over the original name. Also we keep all seen
files and temporary files in a hashtable so we don't accidentally
process anything twice.
There are several reasons to verify these. First of all
we use these as filename elements, so we need to sure that dangerous
things like "..", "/" etc don't appear in them.
Secondly, we want to guarantee that app names are valid dbus well
known bus names as they are used as app-ids in e.g. desktop files.
We also want to enforce the app name as prefix for exported files to
avoid conflicts. This means we disallow two-element names like
"org.gnome", and we disallow "-" in app names, so that "-" can be used
to separate the app name prefix from the rest of the filename. In
particular, this is important for icons, like
"org.gnome.app-symbolic.svg", where we want the only valid prefix to be
org.gnome.app.
When we add a remote, load the summary from the repository, and
use the title if there is one. This at the same time serves as
(minimal) validation of the repository url.
This allows you to set the privs for the helper via file
capabilities instead of setuid.
You can also set the mode to none, but then you have to
manually set either setuid or filecaps (for instance via
a packaging script).
Instead of running as root we setuid to the real user, after
having assured that we have the minimum amount of capabilities
required (which we then drop at the end).
This means we create all files as the actual user, and we never
risk somehow reading a file that otherwise only root could read.
This allows to restrict the access that the app gets out of
the sandbox. We allow an access if the app requests it (in its
metadata) and the user doesn't forbid it (with this option).
The --runtime option lets us completely override the runtime that
is specified in the application metadata. This is useful for testing
compatibility of an application with runtimes.
This will be used later to avoid deleting active mounts.
They have to be created during deploy, because we are
then guaranteed to be able to write to the directory,
and we don't want the resulting file to be hardlinked
to any other deployment (as then locks could be shared).
For the fully sandboxed case we *need* a pid sandbox, so we might as
well always use one to get the same setup always. There should really
be no need for a normal "app" to see host processes.
The other nice thing about this is that we get somewhere to run code
when the app stops, which means we can do things like delay uninstall
while apps are running.
The unfortunate drawback of this is that we get 2 extra processes per
app, one is the pid1 in the sandbox, and the other is the monitor
process to return the exit code to the spawner of xdg-appp-helper.
Rather than do the fork workaround we make / rslave, which means
we will still get new mounts/unmounts propagated to us from the root,
but will not leak any mounts to the host.
We also use a single directory in the users run dir as the mountpoint
for the tmpfs.