FYI, I looked into this and I can confirm.
In strict mode with network-control connected, there are no sandbox denials but there is the Cannot open netlink socket: Operation not permitted
with sudo mytest.add
. In devmode, it works. Deleting the device with sudo mytest.delete
and going back to strict mode, it works.
What is happening is that on boot, the tun module is not loaded and it isn’t autoloading from the strict mode snap:
$ sudo reboot
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu Core 18"
$ snap list|grep pi
pi 18-1 17 18-pi3 canonical* gadget
pi-kernel 4.15.0-1053.57 69 18-pi3 canonical* kernel
$ lsmod|grep tun
$
$ sudo snap install --dangerous ./mytest_0.1_armhf.snap
$ sudo mytest.add
open: Operation not permitted
$ lsmod|grep tun
$ sudo modprobe tun # load the module manually and it works
$ sudo mytest.add
$ sudo mytest.delete
$ sudo rmmod tun # unload the module and it fails again
$ sudo mytest.add
open: Operation not permitted
On the pi3, ‘tun’ is compiled as a module (which isn’t autoloading under strict mode):
$ grep 'CONFIG_TUN=' /snap/*kernel/current/config*
CONFIG_TUN=m
Strace show us:
openat(AT_FDCWD, "/dev/net/tun", O_RDWR|O_LARGEFILE) = -1 EPERM (Operation not permitted)
On a pi2, core16, things work as expected:
$ snap list|grep pi
pi2-kernel 4.4.0-1127.136 105 stable canonical* kernel
pi3 16.04-0.7 32 stable canonical* gadget
$ lsmod|grep tun
$ sudo snap install --dangerous /tmp/mytest_0.1_armhf.snap
$ sudo snap connect mytest:network-control
$ sudo mytest.add
$ sudo mytest.delete
$ lsmod|grep tun
$
‘tun’ is compiled into the kernel. This is confirmed with:
$ grep 'CONFIG_TUN=' /snap/*kernel/current/config*
CONFIG_TUN=y
On amd64 core16, ‘tun’ is also compiled into the kernel:
$ grep 'CONFIG_TUN=' /snap/*kernel/current/config*
CONFIG_TUN=y
With the module unloaded, inspected the snap’s device cgroup and discovered that c 10:200 rwm
was not listed in /sys/fs/cgroup/devices/snap.mytest.add (ls -l /dev/net/tun
shows it is crw-rw-rw- 1 root root 10, 200 Jan 10 14:02 /dev/net/tun
). If I modprobe tun
then c 10:200 rwm
appears.
The symptom of this bug is that we are seeing a device cgroup denial.
What is happening is that /dev/net/tun does not get udev tagged until the module is loaded. The snap is accessing /dev/net/tun directly, but because the udev tagging didn’t happen, this isn’t yet in the device cgroup and the open fails. Because the open failed, the module doesn’t autoload.
First off, we probably should build the tun module into the kernel (CONFIG_TUN=y), which is in alignment with our other kernels (verified on core16/amd64, core16/armhf, are16/arm64, classic 16.04/amd64, classic 18.04/amd64). This will side-step the issue with CONFIG_TUN=m.
To support CONFIG_TUN=m, snap-confine should be adjusted to unconditionally add /dev/net/tun to the device cgroup (if it exists). AppArmor mediates access to /dev/net/tun already, so this is safe. I’ll add this to my next batch of policy updates.