Issue establishing Dbus interface with org.kde.PlasmaShell

I’m trying to snackage my cross platform multi-monitor wallpaper tool: Superpaper on GitHub

Given that I need to interact with varying types of desktops, I’m running into issues with confinement. Most problematic being KDE dbus scripting.

Issue: KDE dbus interface

I’ve tried to define a dbus plug like so:

plugs:
  kde-plasma-dbus:
     bus: session
     interface: dbus
     name: org.kde.PlasmaShell

which is then called under apps:

apps:
  superpaper:
     ...
     plugs:
       ...
       - dbus
       - kde-plasma-dbus

When I install the .snap I get an error:

2020-01-03T15:34:14+02:00 INFO snap “superpaper” has bad plugs or slots: dbus (cannot find attribute ‘bus’)

and when I run the snap I get a specific error:

dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type=“method_call”, sender=":1.186" (uid=1000 pid=23518 comm="/snap/superpaper/x7/usr/bin/python3 /snap/superpap" label=“snap.superpaper.superpaper (enforce)”) interface=“org.kde.PlasmaShell” member=“evaluateScript” error name="(unset)" requested_reply=“0” destination=":1.21" (uid=1000 pid=2059 comm="/usr/bin/plasmashell " label=“unconfined”)

If I try to manually connect the interface I get the error:

snap connect superpaper:kde-plasma-dbus 
error: snap "core" has no "dbus" interface slots

How should I create the interface with the dbus session to get this to work?

Here’s my full recipe

name: superpaper
base: core18
version: '1.2.0'
license: MIT
icon: snap/gui/superpaper.png
summary: Multi-monitor wallpaper manager with spanning, multi image and more.
description: |
  Superpaper is an advanced multi-monitor wallpaper manager
  for GNU/Linux supporting various desktop environments.
  On top of standard spanning and multi image wallpaper features
  it supports spanning corrections for monitor bezels, and if your
  displays don't have the same pixel density it will take that into
  account as well.
  Other features include: slideshow, saving wallpaper setting profiles,
  hotkeys, manual wallpaper offsets, alignment testing tool and
  Windows support. 

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

plugs:
  kde-plasma-dbus:
    bus: session
    interface: dbus
    name: org.kde.PlasmaShell
  freedesktop-dbus:
    bus: session
    interface: dbus
    name: org.freedesktop.DBus

apps:
  superpaper:
    command: bin/superpaper
    plugs:
      - desktop
      - desktop-legacy
      - unity7
      - x11
      - gsettings
      - kde-plasma-dbus
      - freedesktop-dbus
      - dbus
      - home
      - removable-media

parts:
  superpaper:
    plugin: python
    python-version: python3
    source: .
    build-packages:
      - python3-wxgtk4.0
      - python3-wxgtk-media4.0
      - python3-wxgtk-webview4.0
      - python3-dbus
      - libxcb-render0-dev
      - libgdk-pixbuf2.0-dev
    stage-packages:
      - python3-wxgtk4.0
      - python3-wxgtk-media4.0
      - python3-wxgtk-webview4.0
      - python3-dbus
      - libxcb-render0-dev
      - libglu1-mesa
      - libgpm2
      - libslang2
      - libgdk-pixbuf2.0-dev
    requirements: [requirements_full_linux.txt]

Seems to me you shouldn’t use the ‘dbus’ plug under your app. That slot doesn’t exist and is what that error says.

So just the kde-plasma-dbus and freedesktop-dbus.

The dbus interface is intended for you to create a dbus service so that other applications (or the shell) may interact with your application via dbus. It is not used for granting permissions for your application to communicate with other dbus services.

This message:
"
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: An AppArmor policy prevents this sender from sending this message to this recipient; type=“method_call”, sender=":1.186" (uid=1000 pid=23518 comm="/snap/superpaper/x7/usr/bin/python3 /snap/superpap" label=“snap.superpaper.superpaper (enforce)”) interface=“org.kde.PlasmaShell” member=“evaluateScript” error name="(unset)" requested_reply=“0” destination=":1.21" (uid=1000 pid=2059 comm="/usr/bin/plasmashell " label=“unconfined”)
"

indicates that your snap is trying to use the “evaluateScript” method of a process that provides the org.kde.PlasmaShell interface. It would be clearer if you provided the denial from journalctl, but this appears to be https://userbase.kde.org/KDE_System_Administration/PlasmaDesktopScripting and something that has come up before with snaps: https://lists.ubuntu.com/archives/snapcraft/2017-April/003820.html. There are no snapd interfaces that support this and the snap would need to use classic confinement.

Since my response in 2017, we’ve refined our thinking around interfaces like this and classic. The requested access would have your snap send a script over dbus for PlasmaShell to execute. Since plasma shell runs the script in the context of plasma (ie unconfined), this would allow breaking out of application confinement (similar requests came up recently for gnome extensions and nautilus extensions). To prevent sandbox escape, plasma would have to be rearchitected to support running scripts under a different security context. The requirements for classic are understood, but per recent discussions with @pedronis for the analogous gnome extension request, this snap’s use of evaluateScript means it is unfortunately not a candidate classic.

If there was another wallpaper API you could use instead of org.kde.PlasmaShell.evaluateScript, then we could consider adding an interface to snapd for that API so your snap could work with strict confinement.

Thank you for the detailed response. I feared as much that strict confinement would not work.

As far as I know and can find, there is no other API to set wallpapers on KDE Plasma. I take that this means that a snap like this cannot be confined. Do I understand correctly that this use case is not considered viable for a classic confinement release?

If this snap is not considerable as a classic, can it be released in the store under some other confinement like devmode, or is this snap wholly unsuited for the snap store?

Edit:
I’d like to add that from my limited perspective my use case would seem to differ from the gnome and nautilus extensions. This snap is a standard application that has to interact with native APIs of the system to do what it does; it is not built as a system specific extension. Given that the platforms/plasmashell are not likely to be rearchitectured anytime soon, I’d see this as a reason for classic confinement.

The API your snap is using allows for sandbox escape by asking the shell to execute script outside of the security context of the snap with no means of limiting what the script can do. Therefore, yes, the snap cannot be used with strict confinement and, unfortunately, precisely because there is no path forward with regard to rearchitecting plasmashell, it is not a candidate for classic. It is possible for you to use devmode, but devmode snaps by design do not auto-refresh, so this is not a recommended distribution method for your snap. Until the situation changes and wallpaper-specific APIs become available or there is some progress for mediating org.kde.PlasmaShell.evaluateScript, I recommend using traditional packaging methods to distribute your software.

@pedronis - if my assessment is in error, please overrule

Thank you for elaborating on the issue.

[…] outside of the security context of the snap with no means of limiting what the script can do.

In my case the script to be run by evaluateScript is predefined within the Python code of the snap. I admit that my knowledge on security issues is next to non-existent but to me this would seem that the script that is run can at least be vetted? This of course does not help with confinement but to me it would seem that it allows one to see that arbitrary code is not run?