The magic behind snap interfaces

by Igor Ljubuncic on 4 June 2021

Snaps are confined, self-contained applications, designed with portability and security in mind. By default, strictly confined snaps run in isolation, with minimal access to system resources. For instance, they cannot access home, network, audio, or display. To make their snaps usable, developers and publishers can declare a set of interfaces, which allow granular, per-resource access to the underlying system in a secure, controlled manner.

In today’s article, we want to talk a bit more about the mechanics behind the interface. What happens when a developer declares an interface plug in snapcraft.yaml, and when that snap gets installed on a user’s machine?

Declaration

Interfaces consist of two components – slots and plugs. The slot of an interface is a provider of functionality (and access) to a system resource. The plug of an interface is a component of a built snap, which can then connect to the relevant slot, and thus gain access to the underlying resource. Multiple plugs can connect to a specific slot, e.g.: multiple snaps with the home plug can connect to the home slot, and thus gain access to the user’s home directory.

For security reasons, some interfaces can be auto-connected – on snap installation on a client’s machine, the declared plugs will be able to connect to the slots without any manual intervention. In other scenarios, this will not be possible by default. The user will need to manually connect their snap, or request an override from the Snap Store team. In some cases, this functionality may be granted, especially if it’s part of the necessary application functionality. Typical examples would be network control or audio recording capabilities.

In some cases, the snaps will notify you that a specific connection is required. In others, you will need to determine this yourself, perhaps if you encounter a functionality problem. You can also manually choose to connect or disconnect interfaces as you see fit, but be aware that this may alter the application’s expected behavior.

snap connections vlc
Interface               Plug                        Slot                     Notes
audio-playback          vlc:audio-playback          :audio-playback          -
audio-record            vlc:audio-record            -                        -
avahi-control           vlc:avahi-control           -                        -
camera                  vlc:camera                  -                        -
desktop                 vlc:desktop                 :desktop                 -
desktop-legacy          vlc:desktop-legacy          :desktop-legacy          -
dvb                     vlc:dvb                     -                        -
home                    vlc:home                    :home                    -
jack1                   vlc:jack1                   -                        -
mount-observe           vlc:mount-observe           -                        -
mpris                   -                           vlc:mpris                -
network                 vlc:network                 :network                 -   

In the snippet above, the VLC media player has access to a wide range of typical resources required for its functionality. The camera isn’t auto-connected, though. For example, if you need VLC to capture a video stream using the camera device, you will need this interface to be connected. 

sudo snap connect vlc:camera

Now, in a typical snapcraft.yaml file, a plug section declaration may look like this:

apps:
  segfexample:
    command: segfexample
    plugs:
    - home
    - network

If you’re interested in a broader overview of interfaces and specific use cases, we have already covered this in detail in a blog post a while back.

Installation

During the installation, if you install a snap on the command line and you pay attention to the output in your terminal window, you may see a number of messages from the snapd service about mounts, connections, etc. The installation of the snap includes two principal steps:

  • Unpacking of the snap (a compressed Squashfs archive).
  • Configuration of the security profiles.

Once the snap is installed, you can inspect the system configuration. The snapd AppArmor profiles are stored under:

/var/lib/snapd/apparmor/profiles

Depending on how complex your snap is, there may be one or more profiles, e.g.:

-rw-r--r-- 1 root root  4706 Jun  3 12:32 snap-update-ns.segfexample
-rw-r--r-- 1 root root 23379 Jun  3 12:32 snap.segfexample.segfexample

Provided you have the right permissions, you can now open these profiles in a text editor, and examine the contents. You need some familiarity with the AppArmor syntax, but in essence, you will see the capabilities declared in your snapcraft.yaml plug section listed and expanded here


# Description: Can access the network as a client.
#include <abstractions/nameservice>
/run/systemd/resolve/stub-resolv.conf rk,
/etc/mdns.allow r,     # not yet included in the mdns abstraction
network netlink dgram, # not yet included in the nameservice abstraction
...

Source code

If you want to know more about how a particular interface works, you can also look at the snapd source on GitHub. For instance, the home interface. The code declares the slot specifications, including read and auto-connect attributes, and the AppArmor profile details that will be applied on installation. In this example, the profile allows read/write access to all files in the user’s home directory, except for the snap application path and top-level hidden directories, allows creation of new files, allows access to GVFS mounts for files owned by the user, and disallows writes to the bin subdirectory.


const homeBaseDeclarationSlots = `
  home:
    allow-installation:
      slot-snap-type:
        - core
    deny-connection:
      plug-attributes:
        read: all
    deny-auto-connection:
      -
        on-classic: false
      -
        plug-attributes:
          read: all
`
...

Summary

Snap interfaces may look a bit confusing at first, especially since their behavior diverges from the classic Linux model. However, they can be useful in making sure applications only use the necessary system resources. This can improve both security and predictability, and minimize long-term cruft in the system.

If you want to understand exactly what will happen when you declare a plug in your snapcraft.yaml, you can check the snapd source code and/or the AppArmor profiles for the installed snap to get a clearer view on the specific implementation of the security confinement logic. Hopefully, this article makes things simpler, and reveals the “magician’s trick”. Let us know if you have any questions or suggestions on this topic by joining the Snapcraft forum.

Photo by note thanun on Unsplash.

Newsletter Signup

Related posts

Creating Snaps on Ubuntu Touch

This article was written in collaboration with Alfred E. Neumayer of the UBports Project. Tablets, phones and current technology’s capabilities are phenomenal. Who would have thought a thin, light, barely 10 inch device would provide all the power necessary to run Virtual Machines, wherever one desires while powered on battery? That a sma […]

Managing software in complex network environments: the Snap Store Proxy

As enterprises grapple with the evolving landscape of security threats, the need to safeguard internal networks from the broader internet is increasingly important. In environments with restricted internet access, it can be difficult to manage software updates in an easy, reliable way. When managing devices in the field, change management […]

We wish you RISC-V holidays!

There are three types of computer users: the end user, the system administrator, and the involuntary system administrator. As it happens, everyone has found themselves in the last group at some point or another; you sit down to perform a task relevant to your needs or duties, but suddenly the machine does not work as […]