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.
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:
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
- Request information about the snap from snapd.
- Request connection status of network plug from snapd.
- Determine the associated desktop file ID:
/proc/$pid/attr/currentto 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?)
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:
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
- if the snap has the
homeinterface connected, return
read-writefor non-hidden paths in the user’s home directory.
- otherwise return
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.