Alan Griffiths
on 3 July 2020
A snap confined shell based on Mir: Mircade
Mircade: An example snap confined user shell
There are various scenarios and reasons for packaging a Snap confined shell and a selection of applications together in a confined environment. You might have applications that work well together for a particular task; or, you may want to offer a number of alternative applications and have them available on a wide range of target platforms. Mircade illustrates this approach.
Contents of the Mircade snap
The user shell
A user shell is a program that allows the user to interact with the computer. It could be as simple as a command-line shell or as complex as a full desktop environment.
For Mircade I use a modified example Mir shell (egmde) I’ve presented in other writings. This “mircade” version of egmde allows the user to select one of a number of programs and run it all within the Snap confined environment.
egmde:
source: https://github.com/AlanGriffiths/egmde.git
source-branch: mircade
plugin: cmake-with-ppa
ppa: mir-team/release
build-packages:
- pkg-config
- libmiral-dev
- libboost-filesystem-dev
- libfreetype6-dev
- libwayland-dev
- libxkbcommon-dev
- g++
stage-packages:
- try: [libmiral4]
- else: [libmiral3]
- mir-graphics-drivers-desktop
- fonts-freefont-ttf
stage:
- -usr/share/wayland-sessions/egmde.desktop
- -bin/egmde-launch
The applications
A successful “bundled” snap is really down to choosing a compelling set of applications.
I’ve taken a bunch of games from the Ubuntu archive and bundled them into the snap. That choice is only an illustration, there’s no need to choose games, or programs from the archive.
neverball:
plugin: nil
stage-packages:
- neverball
In this example, most of the applications use SDL2 and all use Wayland.
sdl2:
plugin: nil
stage-packages:
- libsdl2-2.0-0
- libsdl2-image-2.0-0
- libsdl2-mixer-2.0-0
- libsdl2-net-2.0-0
I’ve not covered other toolkits in the Mirade example. In spite of this, applications based on GTK, Qt and X11 can also be packaged.
The target platforms
Running on Ubuntu Core
There are a lot of advantages to running Ubuntu Core on IoT devices, and Mircade shows how a bundle of applications can be delivered for this. When installed on Ubuntu Core, Mircade connects to a Wayland server (such as mir-kiosk).
Running on Classic Linux
On Ubuntu Classic there are four ways that Mircade can run, the first three are:
- Connecting to an X11 compositor as a window on a traditional desktop
- Connecting to a Wayland compositor as a fullscreen window on a traditional desktop
- Running directly on the hardware as a graphical login session
For each of these the corresponding interface needs to be connected:
Connecting to an X11 compositor | snap connect mircade:x11 |
Connecting to a Wayland compositor | snap connect mircade:wayland |
Running directly on the hardware | snap connect mircade:login-session-control |
The fourth option, typically on an Ubuntu Server installation, is to run in the same way as on Ubuntu Core using a mir-kiosk
daemon as to access the hardware.
Security: Snap confinement
What does ‘confinement’ mean?
Historically, there’s been a high cost of entry to application development and distribution meaning that developers and packagers have had to establish a reputation and trust. Some people may have suspicions of what applications like Microsoft Office or Google Chrome do. Regardless, there’s no realistic fear that Microsoft or Google will steal money from you or hold information on your computer for ransom.
Remember, running an application on a computer gives it, and by extension, the developers of that application, access to your computer. Without precautions, it gets access to everything you can access. It is not just running an application requires caution: before running an application you have to install it. Traditional packaging solutions such as .deb and .rpm, give root access to your system to the packagers.
Over the years the barrier to entry in application development has become low. Writing an app and getting it into an “app store” has never been easier: application development and packaging is no longer the preserve of a few well-known organizations. The basis for trust that used to exist has been eroded.
Computers are being trusted with more and more sensitive information. We carry pocket computers with us everywhere and trust them to hold personal information including access to bank accounts, credit cards and medical details.
Taking precautions to mitigate the risk posed by untrusted code is where app confinement comes into play. Confining the app at the operating system level restricts its access to your computer to only those things that are needed for it to work.
How does ‘app confinement’ work?
Software developers know that something that sounds simple in the user domain can involve some serious work in the solution domain. App confinement is no exception: we need to consider what the operating system needs to do to confine an app; how that can be controlled; how the user can review and configure the confinement. Mircade provides an example of applications being selected and run with restricted access to the system.
Kernel and userspace
The code running on a computer can be divided into ‘kernel’ and ‘userspace’. The kernel is that part of the operating system that mediates all interaction with hardware and between processes. The userspace is everything that runs within a normal app.
If we write a “hello world” application, the code we write runs in userspace. And so does the output function from the library we use (maybe operator<<()
, or printf()
or …) but at some point it writes to the console and at that point the kernel takes over and, eventually (there may well be further userspace and kernel code executed), some pixels are lit on the screen.
Without the kernel code can’t access your files, it can’t access the internet, it can’t access your keyboard, mouse, touchpad, interact with other processes, etc.
That makes the interface between userspace and kernel a useful place to restrict the activities of a program.
Snaps and AppArmor
AppArmor is an implementation detail of ‘snap confinement’, which is a component of Canonical’s ‘Snap’ packaging format. Snaps make use of lists of AppArmor rules called ‘interfaces’, each of which covers identifiable capabilities. These interfaces are reviewed by the Snap developers and can be enabled (or disabled) by the end user.
These are the permissions used by Mircade:
$ snap connections mircade
Interface Plug Slot Notes
audio-playback mircade:audio-playback :audio-playback -
hardware-observe mircade:hardware-observe - manual
login-session-control mircade:login-session-control - manual
network-bind mircade:network-bind :network-bind -
opengl mircade:opengl :opengl -
wayland mircade:wayland :wayland manual
x11 mircade:x11 :x11 -
Conclusion
The Mircade snap confined shell demonstrates how it is possible to take some applications, a user shell and Snap technology and use them deliver a portable, secure package to multiple Linux platforms including Ubuntu Core, Ubuntu Desktop and many other distros.
Targeting multiple platforms is important to the developers of snaps and confinement is important as users of a snap can ensure that it has limited access to their computer and what they are doing with it.
Do you have, or know of, a set of applications that would benefit from this approach?
References
Mircade on GitHub | https://github.com/MirServer/mircade |
Egmde on GitHub | https://github.com/AlanGriffiths/egmde/ |
The Mir display server | https://mir-server.io/ |