Mount intercept using fuse2fs gives 'permission denied'

I need some clarification on how the ‘security.syscalls.intercept.mount.fuse’ configuration is supposed to work. I have the following set currently on a container:

security.syscalls.intercept.mount: “true”
security.syscalls.intercept.mount.allowed: nfs
security.syscalls.intercept.mount.fuse: ext4=fuse2fs

I have the ‘fuse2fs’ package installed on the host as well as in the container, both at this version:

# apt-cache policy fuse2fs
  Installed: 1.44.1-1ubuntu1.3
  Candidate: 1.44.1-1ubuntu1.3

I have a loopback device added to the container with the following profile:

$ lxc profile show loop
config: {}
description: ""
    gid: "6"
    major: "10"
    minor: "237"
    path: /dev/loop-control
    required: "true"
    type: unix-char
    gid: "6"
    major: "7"
    minor: "63"
    path: /dev/loop63
    required: "true"
    type: unix-block
name: loop
- /1.0/instances/fuse2fs-test

I am trying to mount an ext4 filesystem from a file as follows:

root@fuse2fs-test:~# truncate -s2GiB /tmp/ext4.img
root@fuse2fs-test:~# mkfs.ext4 /tmp/ext4.img 
mke2fs 1.44.1 (24-Mar-2018)
Discarding device blocks: done                            
Creating filesystem with 524288 4k blocks and 131072 inodes
Filesystem UUID: 26eb2bad-809f-4608-a6f5-f36f78622623
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

root@fuse2fs-test:~# losetup /dev/loop63 /tmp/ext4.img 
root@fuse2fs-test:~# losetup -a
/dev/loop63: [0076]:35051 (/tmp/ext4.img)
root@fuse2fs-test:~# mount -o ro,noload /dev/loop63 /mnt
mount: /mnt: permission denied.

I don’t understand where the ‘permission denied’ is coming from. The LXD daemon log in debug mode shows:

t=2020-04-22T14:54:30-0700 lvl=dbug msg=“Handling mount syscall” audit_architecture=3221225534 container=fuse2fs-test fuse_ignored_flags=0 fuse_opts=noload,ro fuse_source=fuse2fs#/dev/loop63 fuse_target=/mnt project=default seccomp_notify_flags=0 seccomp_notify_id=16771764576638936099 syscall_continue=true syscall_number=165

Oddly, the following works from within the container:

root@fuse2fs-test:~# fuse2fs /dev/loop63 /mnt
/dev/loop63: Writing to the journal is not supported.
root@fuse2fs-test:~# ls -la /mnt
total 162
drwxr-xr-x  3 root root  4096 Apr 22 21:53 .
drwxr-xr-x 22 root root    22 Apr  7 15:52 ..
drwx------  2 root root 16384 Apr 22 21:53 lost+found

So, I am wondering that the difference is between using ‘fuse2fs’ directly inside the container vs adding ‘ext4=fuse2fs’ to ‘security.syscalls.intercept.mount.fuse’? When the fuse intercept is defined from what context/namespace is the fuse2fs call being made? The host or the container?

@brauner any idea why intercept lead to that error?

@amcduffee for the FUSE part of intercept, the only advantage, but quite a big one, is that no application changes need to happen. Anything calling mount just works and doesn’t need changes to call fuse2fs instead.

Works fine for me:

root@f2:~# apt install fuse2fs
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
0 upgraded, 1 newly installed, 0 to remove and 57 not upgraded.
Need to get 29.4 kB of archives.
After this operation, 152 kB of additional disk space will be used.
Get:1 focal/universe amd64 fuse2fs amd64 1.45.5-2ubuntu1 [29.4 kB]
Fetched 29.4 kB in 0s (115 kB/s)
Selecting previously unselected package fuse2fs.
(Reading database ... 15304 files and directories currently installed.)
Preparing to unpack .../fuse2fs_1.45.5-2ubuntu1_amd64.deb ...
Unpacking fuse2fs (1.45.5-2ubuntu1) ...
Setting up fuse2fs (1.45.5-2ubuntu1) ...
root@f2:~# mount /dev/loop11 /mnt

With your exact setting.

Did you have fuse2fs installed the first time you called mount inside the container?

It is possible I didn’t have fuse2fs installed the first time I called mount. I have been experimenting with allowed vs fuse methods to understand them better, so possibly fuse2fs wasn’t there to begin with. Does that create a persistent issue?

Is there a difference in your test in regards to how ‘/dev/loop11’ was setup? Did you do losetup for loop11 from the host or the container? I did losetup from the container after adding loop devices through a profile. I should note that loop63 did not exist on the host prior to being added to a container via the ‘loop’ profile from above.

I just tried again with a brand new container on the same host and definitely don’t see correct behaviour:

anderson@ryzen9:~$ lxc launch ubuntu:18.04 f1
Creating f1
Starting f1
anderson@ryzen9:~$ lxc stop f1
anderson@ryzen9:~$ lxc config set f1 security.syscalls.intercept.mount true
anderson@ryzen9:~$ lxc config set f1 security.syscalls.intercept.mount.fuse ext4=fuse2fs
anderson@ryzen9:~$ lxc profile add f1 loop
Profile loop added to f1
anderson@ryzen9:~$ lxc start f1
anderson@ryzen9:~$ lxc exec f1 -- /bin/bash
root@f1:~# apt update
Get:1 bionic-security InRelease [88.7 kB]
10 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@f1:~# apt install fuse2fs
Reading package lists... Done
Setting up fuse2fs (1.44.1-1ubuntu1.3) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
root@f1:~# truncate -s2GiB /tmp/ext4.img
root@f1:~# mkfs.ext4 /tmp/ext4.img
mke2fs 1.44.1 (24-Mar-2018)
Writing superblocks and filesystem accounting information: done 
root@f1:~# losetup /dev/loop63 /tmp/ext4.img
root@f1:~# losetup -a
/dev/loop63: [0076]:36419 (/tmp/ext4.img)
root@f1:~# mount -o ro,noload /dev/loop63 /mnt
root@f1:~# mount | grep loop
/dev/mapper/nvme-root on /dev/loop63 type ext4 (rw,relatime,errors=remount-ro)
/dev/mapper/nvme-root on /dev/loop-control type ext4 (rw,relatime,errors=remount-ro)
root@f1:~# ls -la /mnt/
total 3
drwxr-xr-x  2 root root  2 Apr  7 15:49 .
drwxr-xr-x 22 root root 22 Apr  7 15:52 ..

This time the mount command didn’t fail with an error, instead it silently failed without an error. There is no mount table entry for the loop device and /mnt definitely does not have a mounted ext4 filesystem because the ‘lost+found’ directory is missing.