At GUADEC, I had a number of discussions about improving the snap support in xdg-desktop-portal
. The primary shortcomings of what we currently have are:
- It uses AppArmor labels to detect snapped applications, so does not work correctly on distros that don’t enable AppArmor support.
- Portals APIs like notifications that depend on desktop file IDs do not function, since unlike Flatpaks, snap package names != desktop IDs.
- The document portal assumes snaps can not access any files on the host system, so will proxy all files. For Flatpaks, it avoids proxying files the snap can access directly.
We had a good idea of how to solve most of this in the past, but I had put off working on it since the current solution mostly worked and I had other tasks to deal with. Below is a more concrete sketch of what I think is needed based on those old ideas.
A snap-info
command
We don’t want to introduce new dependencies to xdg-desktop-portal
, since we want snap support to remain part of the default configuration with no incentive to try and disable it. So instead, the we will have xdg-desktop-portal
invoke a snap
subcommand to retrieve the info it needs in a machine readable format.
The exact command name is TBD, but lets pick snap internal snap-info
as a placeholder. As for the machine readable format, I think ini/keyfile format would be the best option: there is a parser for it in glib, and the portal service does not currently depend on any json or yaml parsers. It is also extensible, making it easy to expose more information in future that can be ignored by old versions of the portal software.
The command will be invoked with a process ID as an argument, and output something like the following:
[Snap Package]
InstanceName=<snap package name>
Network=<true/false> # if the network plug is connected
DesktopFile=<desktop file ID>
I expect all of this information can be provided using the existing snapd APIs, so this would only involve changes to the snap
command. It would look roughly like this:
- determine the snap name by checking the freezer cgroup membership in
/proc/$pid/cgroup
. - Request information about the snap from snapd.
- Request connection status of network plug from snapd.
- Determine the associated desktop file ID:
- Check
/proc/$pid/attr/current
to see if we’re confined by AppArmor. If so, use the label to determine which app within the snap we’re talking to, and return its desktop file. - As a fallback, pick the first desktop file returned by snapd. (can we do better?)
- Check
File access check
The document portal currently calls out to the flatpak info
command to determine file access. I suggest we follow the same API, with something like:
snap internal snap-info --file-access=$path $snap_nape
This would then print one of the following: hidden
, read-only
, or read-write
. False negatives are fine here (it would just result in more files being proxied via the document portal). So I think the following rules would be sufficient for a first pass:
- check if the snap is using classic confinement: if so, always return
read-write
. - if the snap has the
home
interface connected, returnread-write
for non-hidden paths in the user’s home directory. - return
read-write
for$SNAP_USER_DATA
,$SNAP_USER_COMMON
,$SNAP_DATA
and$SNAP_COMMON
. - otherwise return
hidden
.
This will return read-write
for files the user can’t write to due to file system permissions, but I think this is the right choice: we won’t be able to turn them into writable paths by proxying them through the document portal.