Inconsistent behaviour in GTK file-open dialogs

Akira is a GTK design program made for elementary OS. I submitted a snapcraft.yaml and it’s currently published in the edge channel. This thread is sparked by an issue filed upstream.

We have a strictly confined snap which behaves surprisingly differently across a number of computers. When saving work, on my Ubuntu 20.04 system, the file dialog appears. On @Wimpress 20.04 system it does not. Same build of the application, snapd, kernel, apparmor, gnome-platform snap. It also fails on an elementary machine. Here’s the errors you get when trying to save your work

alan@deep-thought:~/Akira$ akira
Gtk-Message: 16:19:52.102: Failed to load module "pantheon-filechooser-module"

(Akira:22783): Gtk-WARNING **: 16:19:59.939: Can't open portal file chooser: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type="method_call", sender=":1.396" (uid=1000 pid=22783 comm="/snap/akira/x4/usr/bin/com.github.akiraux.akira " label="snap.akira.akira (enforce)") interface="org.freedesktop.portal.FileChooser" member="SaveFile" error name="(unset)" requested_reply="0" destination="org.freedesktop.portal.Desktop" (bus)

Here’s the apparmor issues:

$ snappy-debug.security scanlog
INFO: Following '/var/log/syslog'. If have dropped messages, use:
INFO: $ sudo journalctl --output=short --follow --all | sudo snappy-debug
sysctl: permission denied on key 'kernel.printk_ratelimit'
= AppArmor =
Time: Apr 15 16:21:13
Log: apparmor="DENIED" operation="open" profile="snap.akira.akira" name="/run/mount/utab" pid=22977 comm="com.github.akir" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
File: /run/mount/utab (read)
Suggestions:
* adjust program to use $SNAP_DATA
* adjust program to use /run/shm/snap.$SNAP_NAME.*
* adjust program to use /run/snap.$SNAP_NAME.*
* adjust snap to use snap layouts (https://forum.snapcraft.io/t/snap-layouts/7207)

= AppArmor =
Time: Apr 15 16:21:13
Log: apparmor="DENIED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/portal/desktop" interface="org.freedesktop.portal.FileChooser" member="SaveFile" mask="send" name="org.freedesktop.portal.Desktop" pid=22977 label="snap.akira.akira"
DBus access

= AppArmor =
Time: Apr 15 16:21:13
Log: apparmor="DENIED" operation="open" profile="snap.akira.akira" name="/run/mount/utab" pid=22977 comm="com.github.akir" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
File: /run/mount/utab (read)
Suggestions:
* adjust program to use $SNAP_DATA
* adjust program to use /run/shm/snap.$SNAP_NAME.*
* adjust program to use /run/snap.$SNAP_NAME.*
* adjust snap to use snap layouts (https://forum.snapcraft.io/t/snap-layouts/7207)

Things we have tried: Adding the home interface, adding and connecting removable-media and mount-observe, rebooting, re-installing, staging libpantheon-filechooser-module.so from the elementary pantheon-files package:

  pantheon-files:
    after: [elementary-sdk]
    plugin: nil
    stage-packages:
      - pantheon-files
    prime:
      - usr/lib/*/gtk-3.0/modules/libpantheon-filechooser-module.so

&

apps:
  akira:
    environment:
      LD_LIBRARY_PATH: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/gtk-3.0/modules/:$LD_LIBRARY_PATH
...

None of this worked.

Why does this behave differently on two seemingly identical installs?
Why does it fail at all?

Steps to reproduce:

  1. snap install akira --edge
  2. snap run akira
  3. Press a, draw a rectangle
  4. Press CTRL+S to save

Sounds like an apparmor / portal / launcher issue, so tagging @jamesh and @jdstrand speculatively :slight_smile:

This is a Wayland issue. It works on X11 but fails in Wayland for me.

Fails on X11 here on elementary OS itself.
Not sure what @Wimpress was using. I’m on X11 and it works.

Perhaps it’s random then? I’ve definitely seen it both fail and work with the only difference being that I rebooted after trying it in Wayland (fail) and tried it on X11 after the reboob where it worked (I had to reboob because akira refused to launch after switching from Wayland to X11 saying it can’t connect to DISPLAY :0, so I rebooted and logged into X11 a second time where it worked)

This may just be noise, but may not considering the operation that is trying to be performed. /run/mount/utab is problematic and discussed here:

@jamesh - do you know if portals requires this access (cc @zyga-snapd for awareness)?

This is intended to be allowed by the desktop interface which has:

# Allow access to xdg-desktop-portal and xdg-document-portal
dbus (receive, send)
    bus=session
    interface=org.freedesktop.portal.*
    path=/org/freedesktop/portal/{desktop,documents}{,/**}
    peer=(label=unconfined),

Perhaps org.freedesktop.portal.Desktop is DBus activated and at the time of the denial it isn’t running yet (there is no ‘peer_label’ in the denial which seems to indicate this)? This might explain some of the intermittentness you are seeing since if it is already running it will work but if it isn’t it won’t.

@jamesh, perhaps this rule should be changed to:

dbus (receive, send)
    bus=session
    interface=org.freedesktop.portal.*
    path=/org/freedesktop/portal/{desktop,documents}{,/**},

@jamesh - what do you think about adding peer=(name=org.freedesktop.portal.Desktop)? Are there times when DBus unique connections names will be used instead (and therefore we shouldn’t use name=)?

1 Like

I’ve just replicated X11 working where Wayland fails. When I get it to fail in Wayland it outputs the following:

(Akira:101580): Gtk-WARNING **: 19:47:45.090: Can't open portal file chooser: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type="method_call", sender=":1.119" (uid=1000 pid=101580 comm="/snap/akira/108/usr/bin/com.github.akiraux.akira " label="snap.akira.akira (enforce)") interface="org.freedesktop.portal.FileChooser" member="SaveFile" error name="(unset)" requested_reply="0" destination="org.freedesktop.portal.Desktop" (bus)

snappy-debug shows these denials when attempting to save:

= AppArmor =
Time: Apr 15 19:49:39
Log: apparmor="DENIED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/portal/desktop" interface="org.freedesktop.portal.FileChooser" member="SaveFile" mask="send" name="org.freedesktop.portal.Desktop" pid=105448 label="snap.akira.akira"
DBus access

= AppArmor =
Time: Apr 15 19:49:39
Log: apparmor="DENIED" operation="open" profile="snap.akira.akira" name="/proc/105448/mountinfo" pid=105448 comm="com.github.akir" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
File: /proc/105448/mountinfo (read)
Suggestions:
* adjust program to not access '@{PROC}/@{pid}/mountinfo'
* add 'mount-observe' to 'plugs'

= AppArmor =
Time: Apr 15 19:49:39
Log: apparmor="DENIED" operation="open" profile="snap.akira.akira" name="/proc/105448/mounts" pid=105448 comm="com.github.akir" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
File: /proc/105448/mounts (read)
Suggestions:
* adjust program to not access '@{PROC}/@{pid}/mounts'
* add one of 'mount-observe, network-control' to 'plugs'

= AppArmor =
Time: Apr 15 19:49:39
Log: apparmor="DENIED" operation="open" profile="snap.akira.akira" name="/proc/105448/mountinfo" pid=105448 comm="com.github.akir" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
File: /proc/105448/mountinfo (read)
Suggestions:
* adjust program to not access '@{PROC}/@{pid}/mountinfo'
* add 'mount-observe' to 'plugs'

This looks to be an issue with activation: the AppArmor rules allow communication with peer=unconfined, but dbus-daemon doesn’t know what AppArmor label xdg-desktop-portal will have before it has been activated. Newer versions of xdg-desktop-portal include the AssumedAppArmor label, but that doesn’t help here:

One of the reasons we didn’t catch this earlier is that most of the portal calls go via a GDBusProxy that issues a StartServiceByName call first. This activates the service without hitting the denial, and further method calls will succeed. In contrast, the portal calls in gtkfilechoosernativeportal.c are coded directly and rely on service activation, which fails here.

From my understanding, the GDBusProxy code will switch to issuing calls to the service’s unique name after activating it, so peer=(name=org.freedesktop.portal.Desktop) alone might break things. Signals broadcast by xdg-desktop-portal would also match against the unique name as sender, IIRC.

Perhaps we need both peer=(name=org.freedesktop.portal.Desktop) and peer=(label=unconfined) rules? Dropping the peer restriction all together would work, but I’m not sure whether you want to poke a hole that big.

We’re suffering from this problem in qelectrotech, with xdg-desktop-portal not being active at the time of the dbus call and therefore no file dialogs appearing.

Is there a short-term fix on the horizon besides manually adding a StartServiceByName call in a launcher script?

Fyi, https://github.com/snapcore/snapd/pull/8793

1 Like