The post details steps needed to get snapd
working on Arch Linux with AppArmor confinement enabled.
The extra/linux-hardened
kernel has AppArmor enabled since 4.17.4, see https://git.archlinux.org/svntogit/packages.git/commit/trunk?h=packages/linux-hardened&id=14eccc6c604d37fa3001146f5bd4ca32ffa15c4f for details. Having installed the kernel it should be possible to use AppArmor for confining snap applications.
Installation
Getting AppArmor to work on Arch is nicely detailed in the wiki page: https://wiki.archlinux.org/index.php/AppArmor
In brief the steps are
$ pacman -Syu linux-hardened
Install apparmor
from AUR. I am lazy and ended up using pacaur
:
$ pacaur -S apparmor
NOTE: Should you hit a problem installing perl-rpc-xml
(which is a dependency), consult the comments in the AUR page: https://aur.archlinux.org/packages/perl-rpc-xml
Lastly, enable apparmor.service
, set up proper entries in your favourite bootloade and make sure to add apparmor=1 security=apparmor
to the kernel command line.
snapd
Once AppArmor is enabled, snapd
will detect that and generate proper profiles for each installed snap. One still needs to:
- rebuild
snap-confine
with AppArmor support - update snapd to not downgrade the confinement in generated profiles (since we have a recent enough kernel)
Apply the following diff to PKGBUILD
to enable AppArmor support in snap-confine:
diff --git a/PKGBUILD b/PKGBUILD
index 57ecfe3..3d9ca6e 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -72,7 +72,7 @@ build() {
--prefix=/usr \
--libexecdir=/usr/lib/snapd \
--with-snap-mount-dir=/var/lib/snapd/snap \
- --disable-apparmor \
+ --enable-apparmor \
--enable-nvidia-biarch \
--enable-merged-usr
make $MAKEFLAGS
Also grab the patch for snapd from here and add it to PKGBUILD:
Once the pull-request lands in master, it will be possible to rebuild snapd-git
package with a simple change to pass --enable-apparmor
in PKGBUILD, no extra patches needed.
Once snapd
is started, check if apparmor was correctly detected:
$ snap debug sandbox-features
apparmor: kernel:caps kernel:domain kernel:file kernel:mount kernel:namespaces kernel:network_v8 kernel:policy kernel:ptrace kernel:query kernel:rlimit kernel:signal
confinement-options: classic devmode
dbus: mediated-bus-access
kmod: mediated-modprobe
mount: freezer-cgroup-v1 layouts-beta mount-namespace per-snap-persistency per-snap-profiles per-snap-updates per-snap-user-profiles stale-base-invalidation
seccomp: bpf-argument-filtering kernel:allow kernel:errno kernel:kill_process kernel:kill_thread kernel:log kernel:trace kernel:trap
udev: device-cgroup-v1 tagging
snaps
$ snap install hello-world
$ snap list
maciek@corsair:arch/aur/snapd (git)-[master] snap list
Name Version Rev Tracking Publisher Notes
core 16-2.34.3 5145 stable canonical? core
hello-world 6.3 27 stable canonical? -
Double check that profiles were generated:
$ ls /var/lib/snapd/apparmor/profiles/snap.hello-world.*
/var/lib/snapd/apparmor/profiles/snap.hello-world.env
/var/lib/snapd/apparmor/profiles/snap.hello-world.evil
/var/lib/snapd/apparmor/profiles/snap.hello-world.hello-world
/var/lib/snapd/apparmor/profiles/snap.hello-world.sh
Verify that snap-confine
profile exists at /etc/apparmor.d/usr.lib.snapd.snap-confine
And that snap-confine
and snap profiles were loaded by AppArmor:
$ sudo apparmor_status
92 profiles are loaded.
89 profiles are in enforce mode.
...
/usr/lib/snapd/snap-confine
/usr/lib/snapd/snap-confine//mount-namespace-capture-helper
snap-update-ns.core
snap-update-ns.hello-world
snap.core.hook.configure
snap.hello-world.env
snap.hello-world.evil
snap.hello-world.hello-world
snap.hello-world.sh
...
2 processes have profiles defined.
...
At this point hello-world.evil
should be correctly blocked:
$ hello-world.evil
Hello Evil World!
This example demonstrates the app confinement
You should see a permission denied error next
/snap/hello-world/27/bin/evil: 9: /snap/hello-world/27/bin/evil: cannot create /var/tmp/myevil.txt: Permission denied
And you should see a denial in dmesg
like this:
[ 7937.185833] audit: type=1400 audit(1535115949.343:578): apparmor="DENIED"
operation="open" profile="snap.hello-world.evil"
name="/var/tmp/myevil.txt"
pid=17653 comm="evil" requested_mask="wc" denied_mask="wc"
fsuid=1000 ouid=1000
The non-evil hello-world should still work:
$ hello-world
Hello World!