Raspberry Pi 3 Ubuntu Core 18 network-control interface issue

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.

1 Like