kdave / btrfs-progs

Development of userspace BTRFS tools
GNU General Public License v2.0
557 stars 242 forks source link

Stacked FUSE mounts breaks mkfs.btrfs: `ERROR: cannot check mount status of DEV: Permission denied` #392

Open rfjakob opened 3 years ago

rfjakob commented 3 years ago

Compiled right now from e4ac7d4f67b330a3b27a4a50f73e94b1e072ae56 .

Trying mkfs.btrfs:

[root@brikett btrfs-progs]# ./mkfs.btrfs /tmp/b.img 
btrfs-progs v5.13.1 
See http://btrfs.wiki.kernel.org for more information.

ERROR: cannot check mount status of /tmp/b.img: Permission denied

Trying mkfs.btrfs -f:

[root@brikett btrfs-progs]# ./mkfs.btrfs -f /tmp/b.img 
btrfs-progs v5.13.1 
See http://btrfs.wiki.kernel.org for more information.

ERROR: cannot check mount status of /tmp/b.img: Permission denied

strace

strace shows that it chokes on a FUSE filesystem (gocryptfs in this case) mounted by a non-root user:

newfstatat(AT_FDCWD, "/tmp/gocryptfs-test-parent-1026/897757635/b", 0x7ffdccee62d0, 0) = -1 EACCES (Permission denied)
close(4)                                = 0
close(3)                                = 0
write(2, "ERROR: ", 7ERROR: )                  = 7
write(2, "cannot check mount status of /tm"..., 58cannot check mount status of /tmp/b.img: Permission denied) = 58
rfjakob commented 3 years ago

mkfs.ext4 does not care:

[root@brikett btrfs-progs]# mkfs.ext4 /tmp/b.img 
mke2fs 1.45.6 (20-Mar-2020)
Discarding device blocks: done                            
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 3bf66b3f-939a-40f6-94fe-27e30eb381d9
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
kdave commented 3 years ago

I can't reproduce it, using sshfs as the FUSE mount. Is there anything special needed for the FUSE mount?

rfjakob commented 3 years ago

Oh. I only now realize that mount was indeed special. It was a leftover from an automated gocryptfs test.

The key point is that the first field in /proc/self/mounts is on a FUSE mount. mkfs.btrfs seems to iterate over the first field.

Repro goes like this (needs gocryptfs, apt install gocryptfs):

mkdir /tmp/392
cd /tmp/392
mkdir a b c
gocryptfs -init a
gocryptfs a b
gocryptfs -init b
gocryptfs b c

Situation in /proc/self/mounts

tail -2 /proc/self/mounts
/tmp/392/a /tmp/392/b fuse.gocryptfs rw,nosuid,nodev,relatime,user_id=1026,group_id=1026,max_read=131072 0 0
/tmp/392/b /tmp/392/c fuse.gocryptfs rw,nosuid,nodev,relatime,user_id=1026,group_id=1026,max_read=131072 0 0

trying mkfs:

sudo mkfs.btrfs /tmp/b.img 
btrfs-progs v5.13 
See http://btrfs.wiki.kernel.org for more information.

ERROR: cannot check mount status of /tmp/b.img: Permission denied
rfjakob commented 3 years ago

Note: the reproducer is stupid as it stacks gocryptfs with gocryptfs. A useful case is stacking gocryptfs on top of sshfs, which gives the same problem.