Cannot format FUSE partition - Permission denied

ghz 8months ago ⋅ 84 views

TL;DR

Attempting to format a block device on my FUSE file system fails with EPERM at the open syscall. Permissions are set to 777 and the necessary ioctls are stubbed, but no logs are printed from within the FUSE handler.

Background

I'm writing a program to create virtual disk images. One of my criteria is that it must be able to run with zero superuser access, meaning I can't mount loopback devices, change owners of files or even edit /etc/fuse.conf. For this reason, my approach ends up being fairly long-winded. Specifically, in order to format the various partitions on the disk, I would like to be able to use system tools, because that gives me a far greater range of possible file systems. This involves exposing the various partitions on the VDisk as block devices to the system. However, all the possible methods I've found have required either nbds or loopback devices. Both of which require superuser access.

Implementing FUSE myself

However, implementing block devices in FUSE is not only possible, but supported. Unfortunately, I wasn't able to find much documentation on the matter and since I'm doing all this in Rust, the documentation world for this is even more scarce.

I've implemented the following FUSE methods:

  • init

  • lookup

  • getattr

  • open

  • read

  • write

  • readdir

  • ioctl
    
    • BLKGETSIZE
    • BLKFLSBUF
    • BLKSSZGET

I can list the contents of the file system and get directory/file information. I'm deliberately ignoring methods which create or modify resources, as this is done through the build process.

The error

As mentioned, I get permission denied (EPERM) error. straceing the mkfs call shows that it's the open call to the block device that fails on the kernel side. Full strace result.

execve("/usr/sbin/mkfs.fat", ["mkfs.fat", "out/partitions/EFI"], 0x7ffd42f64ab8 /* 76 vars */) = 0

    --- snip ---

openat(AT_FDCWD, "out/partitions/EFI", O_RDWR|O_EXCL) = -1 EACCES (Permission denied)
write(2, "mkfs.fat: unable to open out/par"..., 63mkfs.fat: unable to open out/partitions/EFI: Permission denied
) = 63
exit_group(1)                           = ?

For clarity, my directory structure looks like this:

out
├── minimal.qcow2 [raw disk image] (shadows minimal.qcow2 [qcow2 file] with qemu-storage-daemon)
├── partitions
│   ├── EFI [Block device]
│   └── System [Block device]
└── qemu-monitor.sock [UNIX domain socket]

Of course, there are logging functions tracing every method. I do see logs when listing out the partitions, but not when formatting.

As I mentioned, I've found very little documentation on what could actually be causing this error.

Further insights

Thanks to the insights from @orenkishon, I've found some more details that just baffle me.

  1. I found some options in fuser which were interesting:

    • MountOption::Dev Enable special character and block devices
    • MountOption::DefaultPermission Enable permission checking in the kernel
    • MountOption::RW Read-write filesystem (apparently not a default option)

    Unfortunately, no combination of which resolved my issue.

  2. Log functions aren't called immediately. They seem to be tied to some sort of flushing operation. I can run the mkfs.fat command, see one or two logs, switch back to my IDE and see a page worth of logs appear.

    This may be due to the fact that the directory I'm generating the files is within the project's directory, so it is visible to the IDE, but it strikes me as very unusual.

  3. The log in the access function is never visible, but in the statfs function is, but only if mkfs is called from outside the out directory and is the first of any mkfs calls.

    project > cd ./out
    project/out > mkfs.fat partitions/EFI
    mkfs.fat 4.2 (2021-01-31)
    mkfs.fat: unable to open partitions/EFI: Permission denied
    
    # No logs
    
    project > mkfs.fat out/partitions/EFI
    mkfs.fat 4.2 (2021-01-31)
    mkfs.fat: unable to open out/partitions/EFI: Permission denied
    
    # No logs
    project > cargo run ...
    project > mkfs.fat out/partitions
    mkfs.fat 4.2 (2021-01-31)
    mkfs.fat: unable to open out/partitions/EFI: Permission denied
    
    # Logs appear after switching to IDE
    

    Answers

    It sounds like you're encountering issues with permission when trying to format a block device on your FUSE file system. Here are a few things you can check and consider:

  4. Ensure Correct Permissions: You mentioned that the permissions are set to 777, but double-check that the permissions on the block device file itself (partitions/EFI) allow the user running the mkfs command to access it. Also, ensure that the directory permissions of out/partitions allow the user to create and modify files within it.

  5. Check SELinux/AppArmor: If you're running SELinux or AppArmor, they might be restricting the access to the block device. Check the security policies and logs related to them to see if they're blocking any operations.

  6. Filesystem Type Compatibility: Ensure that the filesystem type you're trying to format (mkfs.fat) is compatible with the block device you're using. Some filesystem types might require specific features or settings on the underlying device.

  7. Logging: Since you mentioned that logging functions are not immediately called but seem to be tied to some flushing operation, ensure that your logging mechanism is properly synchronized and flushing logs when necessary. It's possible that the logs are buffered and not immediately visible due to this behavior.

  8. FUSE Mount Options: Experiment with different FUSE mount options. For example, try enabling special character and block devices (MountOption::Dev) and check if it affects the behavior.

  9. Test with Different Paths: Test formatting the block device using absolute paths (/path/to/your/device) instead of relative paths (out/partitions/EFI). This can help rule out any issues related to the current working directory.

  10. Check Kernel Logs: Look into the kernel logs (dmesg or /var/log/messages) for any relevant error messages or warnings that might shed light on the permission denied issue.

  11. Consider Alternative Approaches: If all else fails, consider alternative approaches such as using privileged helper programs or different filesystem types that don't require formatting via mkfs.

By systematically checking these points and experimenting with different configurations, you should be able to narrow down the cause of the permission denied error and find a resolution.