FUSEファイルシステムでブロックデバイスをフォーマットするときのEPERM

FUSEファイルシステムでブロックデバイスをフォーマットするときのEPERM

長い話を短く

FUSEファイルシステムでブロックデバイスをフォーマットしようとすると、システムコールがEPERM失敗しました。open権限は次のように設定されます。777話必要なioctlsはスタブされますが、FUSEハンドラ内にログは印刷されません。

背景

仮想ディスクイメージを作成するプログラムを作成しています。私の基準の1つは、スーパーユーザーアクセスがまったくない状態で実行できる必要があることでした。つまり、ループバックデバイスをインストールできず、ファイル所有者を変更できず、編集することもできませんでした。/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]

もちろん、各メソッドを追跡するロギング機能もあります。パーティションを一覧表示するとログが表示されますが、フォーマットするとログは表示されません。

前述のように、実際にこのエラーの原因が何であるかについての文書はほとんど見つかりませんでした。

追加の洞察

@ore​​nkishonの洞察力のおかげで、私は混乱していた詳細をもっと見つけました。

  1. fuserいくつかの興味深いオプションが見つかりました。

    • MountOption::Dev 特殊文字とブロックデバイスの有効化
    • MountOption::DefaultPermission カーネルで権限検証を有効にする
    • MountOption::RW ファイルシステムの読み書き(もちろんデフォルトオプションではありません)

    残念ながら、これらの組み合わせのどれも私の問題を解決できませんでした。

  2. ロギング関数はすぐには呼び出されません。一種のフラッシュ操作と関連があるようです。コマンドを実行しmkfs.fat、1つまたは2つのログを表示し、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ブロックおよび文字デバイスのサポートを追加すると推定される特定のデバイスが1つあります。しかし、なぜ拒否されたのかを説明することはできません。パッチ版が使えばいいのにlibfuse3そうではないようです。

便利な追加情報

システム仕様

KDEのシステム情報から直接コピー

  • オペレーティングシステム:Kubuntu 23.10
  • KDEプラズマバージョン:5.27.8
  • KDEフレームワークバージョン:5.110.0
  • Qtバージョン:5.15.10
  • カーネルバージョン:6.5.0-28-typ(64ビット)
  • グラフィックプラットフォーム: Wayland
  • プロセッサー: 32 13世代 Intel® Core™ i9-13900
  • メモリ:31.1GiB RAM
  • グラフィックプロセッサ:AMD Radeon RX 7900 XT
  • メーカー: ASUS

通常の書き込み操作も失敗します。

1つの提案は、ブロックデバイスがサポートされていないと失敗することを確認することですmkfsfat32しかし、別のファイルシステムでフォーマットしても同じ結果が得られるので、これは本当ではないようです。

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実際には通常のファイルである偽のデバイスからいくつかのパーティションを偽にすることができます。これが役に立つかどうかはわかりませんが、覚えておくことをお勧めします。

関連情報