How can snap applications view the manual permissions they have been granted?

Is there a method for a Snap app to introspect its own permissions?

I’ve built an app that requires the raw-usb permission to flash firmware on microcontrollers. Without it, the app does not work and I would like to inform the user with a pop-up that they have to add the permissions. Is there a way that allows the app to explicitly check which permissions have been granted? I have not found any information in the meta folder of the snap app.

For the password-manager-service permission I currently check it via an error thrown by the password library.

You can use snapctl is-connected raw-usb (works for every interface and returns non-zero if the interface is not connected… note that snapctl is only available inside the snap environment)… you can use that inside a command-chain script to check and show a pop-up on startup…

There is no way to see if an interface was manually connected or any equivalent of snap connections... from inside a snap though… might be an interesting feature to have in snapd.

1 Like

Works great. There is just a typo in you command: snapctl is-connected raw-usb

As reference, to quickly test it use: snap run --shell <snap-name> to open a shell and access the env variables and snapctl from the view of the app.

1 Like

I tried to achieve the same thing in a Unity based game to see whether it has microphone permission (audio-record).

First I noticed that snapctl is not on the path, actually not even in /usr/bin but I had to rather invoke it from /snap/snapd/current/usr/lib/snapd/snapctl. When finding that location I got this message in the error output stream:

error: cannot communicate with server: Post "http://localhost/v2/snapctl": dial unix /run/snapd-snap.socket: connect: no such file or directory

Inspecting /run I do indeed see there’s no such socket file:

Contents of /run:
  dbus/
  host/
  pressure-vessel/
  systemd/
  udev/
  user/

(At least assuming that Unity’s Mono implementation would list socket files with DirectoryInfo.GetFiles)

We don’t actually build or ship as Snap but this is Steam running as Snap, invoking our game within. It’s still running in the Steam’s Snap context - the SNAP_NAME environment variable is set to “steam” and I can confirm that connecting/disconnecting the “audio-record” plug to the Steam snap makes the microphone work/not work in the game. Using snap run --shell steam on the host and then invoking the snapctl commands inside works fine, the paths are as expected (snapctl living in /usr/bin, socket file exists).

So I don’t see why this would not work within the actual game, i.e. a child process of Steam running inside the actual Snap. Any hints or ideas what to do/check?

No one with any ideas? :slight_smile:

Steam runs the games in a second container layer, so your games view of Linux on Steam is generally one of the three Steam Platform Runtimes rather than the OS or the package manager in contexts like Snap or Flatpak, you’d have to find a way to access the snapd binary path from inside the containers known as pressure vessel which come in 3 Team Fortress Two inspired versions, Scout, Soldier, and I’m a little forgetful but I think the Heavy.

As of recently, even the Steam application itself runs in this runtime, so the effect that Snap has on the files your game see is much more restricted due to the Steam components rather than snapd itself, I’d look up their documentation to see if there’s a path back into the host namespace, similar to snaps own /var/lib/snapd/hostfs view, although in this case, the “host” to steam would be the core snap, rather than the real host.

This would be applicable to steam on all Linux, not just Snap, and including e.g., unsandboxed “native” installs.

1 Like

Thanks a lot! The part with the Steam runtime was crucial here … for the regular (non-Snap) installation this does not really change anything as microphone access is available anyway and file access seems to work normally.

But with the Snap one not being able to run snapctl to actually verify that permission exists is an issue and I wonder what I can do about this. But thanks to your pointer I have some stuff to read up on :slight_smile:

Got it working, thanks to your pointer James-Carroll!

In case anyone else runs into this, this is what we’re doing now:

  • Test if game is running in Snap container (check if environment variable “SNAP_NAME” is set)
    • If not, nothing further to be done
  • Test if running inside SteamRuntime
    • If yes: Run /usr/bin/steam-runtime-launch-client --alongside-steam -- /usr/bin/snapctl is-connected audio-record
    • If no: Run /usr/bin/snapctl is-connected audio-record directly
1 Like

Thank’s for popping back and giving the solution. :slight_smile: That’s really valuable knowledge for the community.

Incidentally I was thinking about this earlier and kicked myself for this awful mistake;

I think the Heavy

It’s Sniper! And I should really know that off by heart.

Super nerd edit: There was infact, at one point, Heavy.

1 Like