Xdg-desktop-portal proof of concept demo

This is a follow up to the xdg-desktop-portal discussions. I’ve put together a proof of concept for a snap confined application talking to the outside world via the portal.

This is definitely not production ready: it is fragile, and a number of the changes are not suitable for submission upstream.

Installation

Add the following PPA to your system (currently only contains packages for Artful):

(note: still waiting for Launchpad to build the -0jamesh4 version of snapd, which contains some AppArmor policy fixes)

With the PPA enabled, ensure you’ve got snapd, flatpak, xdg-desktop-portal, and xdg-desktop-portal-gtk installed.

Next, edit /etc/fuse.conf and uncomment the line user_allow_other. This is needed because snap-confine runs as root, which by default won’t be able to see FUSE file systems owned by a regular user (as covered in this thread).

Download the following test package:

http://people.canonical.com/~jamesh/portal-test_1_amd64.snap

… then install it and connect up the xdg-desktop-portal interface:

snap install --dangerous portal-test_1_amd64.snap
snap connect portal-test:xdg-desktop-portal

Note that the snap is not connected to the home interface.

Running the test app

Since snapd does not support per-user mounts, my modified snapd package will only set up the document portal mounts correctly for the first user. So if your user ID is not 1000, switch to the that account first.

Next, ensure that the document portal service is running, so its FUSE file system (/run/user/1000/doc) is mounted:

systemctl --user start xdg-document-portal.service

Now run the test application:

portal-test

Not everything in the test app is hooked up, but enough is to show it talking to xdg-desktop-portal:

  1. Click on the button labelled “File Chooser”. A file open dialog should open that lets you see all of your files. This is possible because the dialog box is running outside of the sandbox. When you select a file, the path passed to the confined app will be something like /run/user/1000/doc/random-id/filename.

  2. Click on the button labelled “Open”. You should get a similar file open dialog box, but with far more restricted access: this one is running in process within the sandbox.

  3. Click the text “GNOME”. This should open a page in your default web browser.

  4. Click the “Screenshot” button. A screenshot will be taken, and you will be asked whether you want to grant the application access. The screenshot will be provided via the document portal.

  5. The network connectivity state is made available to the confined app without needing access to NetworkManager.

Branches

I had to modify a number of components to get this demo working:

The test application is https://github.com/matthiasclasen/portal-test built with a simple snapcraft.yaml. The only changes of note were to set the GTK_USE_PORTAL environment variable, and ship with a new enough version of GTK.

4 Likes

This is awesome!

I’ve tried it with the text editor kate, alas, the confinement rule in snapd still seems too strict for our Qt portal integration.

Okt 27 11:28:40 polaris dbus[2519]: apparmor="DENIED" operation="dbus_signal" bus="session" path="/org/freedesktop/portal/desktop/request/308506705" interface="org.freedesktop.portal.Request" member="Response" name=":1.45" mask="receive" pid=3443 label="snap.kate.kate" peer_pid=6199 peer_label="unconfined"

What happens is that the portal plugin wants to wait for the (host) file dialog to come back with a result by listening for the Response signal which unfortunately gets rejected by the confinement so the app is stuck on that.

https://cgit.kde.org/flatpak-platform-plugin.git/tree/src/qflatpakfiledialog.cpp#n285

To try:

wget https://metadata.neon.kde.org/snap/kate_master+2e7cb24_amd64.snap
snap install --force-dangerous kate_master+2e7cb24_amd64.snap
snap connect kate:xdg-desktop-portal
snap run kate
# ctrl-o and open a file

(this snap is standalone from the kde-framworks-5 content snap and defaults to portals - only use for testing purposes)

I also tried with the snap in devmode for good measure and it seems to be working (albeit a bit wobbly; writing failed at least the first time I tried it), so this definitely is heading into a good direction. The lack of feedback from the flatpak people on the PRs is a bit, ehm, concering.

@jamesh - your PR could include this in xdgDesktopPortalConnectedPlugAppArmor, which should make things get farther along:

dbus (receive)
    bus=session
    interface="org.freedesktop.portal.Request"
    path="/org/freedesktop/portal/desktop/request/*"
    member=Response
    peer=(label=unconfined),

@jamesh - I think your PR may predate the decisions surrounding the desktop interface, but I think that instead of xdg-desktop-portal as a separate interface we would want the plugs part in ‘desktop’. That said, if you feel that the slot side should be provided by a snap and not an implicit interface, we would have to discuss the best course of action (with @niemeyer). Perhaps this is moving all the slot parts into ‘desktop’, but that feels slightly weird (maybe its ok, let’s discuss later). For now, consider this food for thought.

@sitter - can you add the above rule to /var/lib/snapd/apparmor/profiles/snap.kate.kate, then load the policy into the kernel with “sudo apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.kate.kate”, try again and report back?

The new dbus(receive) rule makes reading fully work :+1:

For file writing there still seems a problem, which probably stems from kate’s fairly involved writing magic.

journald records the following

Nov 03 14:11:18 polaris kernel: audit: type=1326 audit(1509714678.698:232): auid=1000 uid=1000 gid=1000 ses=3 pid=18098 comm="kate" exe="/snap/kate/x4/usr/bin/kate" sig=31 arch=c000003e syscall=93 compat=0 ip=0x7f336302c2f7 code=0x0

which is caused by the chown here

(it is called with reasonable, albeit supposedly noop arguments)

kate(17882)/(default) Kate::TextBuffer::save: set owner "/run/user/1000/doc/b6c785ec/files" QSaveFile
kate(17882)/(default) SecureTextBuffer::setOwner: fchown( 16 ,  1000 ,  1000 )

Allowing chown to the invoking user is something that is going to be fixed as part Multiple users and groups in snaps. This is something that I’m working on in the background, so progress is ongoing, but slow. Thanks for the feedback!

I finally got round to updating my user-mounts pull request based on some feedback from @zyga-snapd:

Once this gets polished off, I want to look at pushing the remaining portal work through. As @jdstrand said above, it makes most sense to fold portal access into the desktop interface, so that’s what I’ll do.

The user-mounts PR is the basis for getting xdg-document-portal working: it lets us perform additional mounts under the real UID, so it should be possible to bind mount directories inside the portal’s FUSE file system (so no need to disable FUSE security).

The xdg-desktop-portal and flatpak branches will need to be rebased and submitted upstream. That should be one of the easier tasks though.

1 Like

We just had a call to sync up on the progress of this work. Here are the details: