在 FUSE 檔案系統上格式化區塊裝置時的 EPERM

在 FUSE 檔案系統上格式化區塊裝置時的 EPERM

長話短說

嘗試格式化 FUSE 檔案系統上的區塊裝置EPERMopen系統呼叫時失敗。權限設定為第777章且必要的ioctls 已被存根,但 FUSE 處理程序內不會列印任何日誌。

背景

我正在編寫一個程式來創建虛擬磁碟映像。我的標準之一是它必須能夠以零超級使用者存取權限運行,這意味著我無法安裝環回裝置、更改檔案擁有者甚至編輯/etc/fuse.conf。出於這個原因,我的方法最終變得相當冗長。具體來說,為了格式化磁碟上的各個分割區,我希望能夠使用系統工具,因為這為我提供了更大範圍的可能檔案系統。這涉及將VDisk上的各個分區作為區塊設備暴露給系統。然而,我發現的所有可能的方法都需要nbds 或環回設備。兩者都需要超級用戶存取權限。

自己實作FUSE

然而,在 FUSE 中實現區塊設備不僅是可能的,而且是受支援的。不幸的是,我無法找到關於此事的太多文檔,而且由於我正在 Rust 中完成所有這些工作,因此相關文檔更加稀缺。

我已經實作了以下 FUSE 方法:

  • init
  • lookup
  • getattr
  • open
  • read
  • write
  • readdir
  • ioctl
    • BLKGETSIZE
    • BLKFLSBUF
    • BLKSSZGET

我可以列出檔案系統的內容並取得目錄/檔案資訊。我故意忽略創建或修改資源的方法,因為這是透過建置過程完成的。

錯誤

如前所述,我得到沒有權限EPERM) 錯誤。strace呼叫該mkfs呼叫表明對open塊設備的呼叫在核心端失敗。完整strace結果

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)                           = ?

為了清楚起見,我的目錄結構如下:

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]

當然,有追蹤每個方法的日誌記錄功能。我在列出分割區時確實看到了日誌,但在格式化時卻看不到日誌。

正如我所提到的,我發現關於實際可能導致此錯誤的原因的文檔很少。

進一步的見解

感謝@orenkishon 的見解,我發現了更多令我困惑的細節。

  1. fuser我發現了一些有趣的選項:

    • MountOption::Dev 啟用特殊字元和區塊設備
    • MountOption::DefaultPermission 在核心中啟用權限檢查
    • MountOption::RW 讀寫檔案系統(顯然不是預設選項)

    不幸的是,這些組合都沒有解決我的問題。

  2. 不會立即呼叫日誌函數。它們似乎與某種沖洗操作有關。我可以執行該mkfs.fat命令,查看一兩個日誌,切換回 IDE,然後查看顯示的一頁日誌。

    這可能是因為我產生檔案的目錄位於專案目錄內,因此它對 IDE 是可見的,但它讓我覺得非常不尋常。

  3. 函數中的日誌access永遠不可見,但在statfs函數中是可見的,但僅當從目錄mkfs外部呼叫時才可見out是所有呼叫中的第一個mkfs

    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
    
  1. 我今天第一次看到這條日誌訊息:
[2024-04-21T16:58:24Z DEBUG fuser::mnt::fuse_pure] fusermount: 
[2024-04-21T16:58:24Z DEBUG fuser::mnt::fuse_pure] fusermount: fusermount3: unsafe option dev ignored

有一個MountOption::Dev特定的,據說它增加了對塊和字元設備的支援。但我似乎無法解釋為什麼它被拒絕。我希望我可以使用修補版本,libfuse3但似乎沒有。

可能有用的額外信息

系統規格

直接從 KDE 的系統資訊複製

  • 作業系統:Kubuntu 23.10
  • KDE 等離子版本:5.27.8
  • KDE 框架版本:5.110.0
  • Qt 版本:5.15.10
  • 核心版本:6.5.0-28-generic(64位元)
  • 圖形平台:Wayland
  • 處理器:32 代第 13 代智慧型英特爾® 酷睿™ i9-13900
  • 內存:31.1 GiB RAM
  • 圖形處理器:AMD Radeon RX 7900 XT
  • 製造商: 華碩

通用寫入操作也會失敗

一個建議是檢查是否在不支援區塊設備的mkfs情況下失敗。fat32然而,情況似乎並非如此,因為使用任何其他檔案系統進行格式化都會產生相同的結果。

我還使用它mkfs作為測試平台,因為我目前不知道有任何其他現成的系統實用程式可以直接寫入區塊設備,並且mkfs無論如何我都打算使用它。

壞消息 :(

在閱讀手冊頁時我遇到了這一段這讓我的心沉了下去:

支援 mount 中所述的大多數通用掛載選項(ro、rw、suid、nosuid、dev、nodev、exec、noexec、atime、noatime、sync、async、dirsync)。檔案系統預設使用nodev,nosuid掛載,只能由特權使用者覆蓋。

所以看起來這是不可能的。儘管如此,這裡的任何見解——任何一線希望——都將受到高度讚賞。

答案1

如果我理解正確的話,您透過 FUSE 檔案系統公開了一個區塊設備,出於安全原因,這不起作用。

在類別 Unix 系統中,檔案不只是檔案。讓非特權使用者建立任意區塊設備是有問題的,因為透過建立與 rootfs 設備對應的區塊設備,系統可能會受到損害。

您可能想看看該程式的作用fakeroot。它掛鉤libc您在其下運行的程式所使用的每個函數。每當完成需要存取的操作root(例如建立設備)時,都會記錄該操作。稍後fakeroot將偽造禁止文件的存在。

由於您只想公開分區,因此您可以採取類似的方法並ioctl在假設備上偽造一些分區,而實際上它只是一個常規文件。我不確定這會有幫助,但記住這一點是件好事。

相關內容