Skip to content
KitploitKITPLOIT
ツールブログ
Log in
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
btrfs_fixes — btrfs check --repair が失敗する(セグフォ、ループ、デッドロック)ような深刻なエクステントツリーの破損に対するカスタムBTRFS修復ツール | Kitploit
ツール/GitHubGitHub/msedek/btrfs_fixes
脆弱性分析フォレンジックデータ復旧論文と研究学習と教育
GitHubmsedek/btrfs_fixes

btrfs_fixes

btrfs check --repair が失敗する(セグフォ、ループ、デッドロック)ような深刻なエクステントツリーの破損に対するカスタムBTRFS修復ツール

リポジトリを見る
9165ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

btrfs_fixes: カスタム BTRFS リペアツール

12TB マルチデバイス BTRFS プールにおいて、ネイティブコマンド(btrfs check --repair、--init-extent-tree など)では修復できなかった深刻なエクステントツリーの破損を回復するために作成されたカスタムツールです。

構造化されたリカバリのケーススタディ、根本原因の分類、およびこれらのツールのほとんどを不要にするはずだった上流 btrfs-progs の改善提案については、INCIDENT-ANALYSIS.md を参照してください。

これらのツールを使用するタイミング

これらのツールは、btrfs check --repair がセグフォルトする、無限ループに入る、またはファイルシステムを以前よりも悪化させる場合にのみ使用してください。

これらのツールが役立つことが確認されているケース:

  • btrfs check --repair が [3/8] checking extents でセグフォルトする (Issue #525)
  • btrfs check --init-extent-tree がデッドロックする
  • btrfs check --repair が同じ修復を繰り返す無限ループに入る
  • 間違った owner/level/generation を持つ数千の METADATA_ITEM が存在するエクステントツリー
  • 他のツリーで再利用されたブロックを参照する古い子ポインタを持つ FS_TREE
  • rescue=all,ro でのみマウントでき、RW マウントに失敗するプール

これらのツールは軽微な破損には使用しないでください。 通常の損傷の場合は、まず btrfs check --repair を試してください。

警告

  • --write 付きでツールを実行する前に、必ずメタデータをバックアップしてください:
    for DEV in sda1 sdb1 sdc1; do
      sudo dd if=/dev/$DEV of=sb_${DEV}.bin bs=4096 count=1 skip=16
    done
    
  • これらのツールはファイルシステムに不可逆的な変更を加えます
  • すべてデフォルトではスキャン専用モードです(--write はオプトイン)
  • これらのツールを実行するときは、ファイルシステムがアンマウントされている必要があります
  • EEXIST パッチが適用された btrfs-progs v6.19.1 または同等のバージョンが必要です

ビルド

ツールは内部の btrfs-progs API を使用しており、btrfs-progs ソースツリー内でビルドする必要があります:

# 1. btrfs-progs のクローン
git clone --depth 1 --branch v6.19.1 https://github.com/kdave/btrfs-progs.git
cd btrfs-progs

# 2. EEXIST パッチの適用(バッチバック参照注入に必要)
patch -p1 < path/to/btrfs_fixes/patches/alloc_reserved_tree_block_eexist.patch

# 3. ベースとなる btrfs-progs の構成とビルド
./autogen.sh
./configure
make -j$(nproc)

# 4. このリポジトリから .c ファイルを btrfs-progs ディレクトリにコピー
cp path/to/btrfs_fixes/programs/*.c .

# 5. 各プログラムを Makefile に追加:
echo '
PROGNAME: PROGNAME.o $(objects) $(libs_shared)
	@echo "  [LD]    $@"
	$(Q)$(CC) -o $@ PROGNAME.o $(objects) $(libs_shared) $(LDFLAGS) $(LIBS)
' >> Makefile

# 6. ビルド
make PROGNAME

ツール

推奨される実行順序:

1. scan_and_fix_all_backrefs.c (最も重要)

最も重要なツールです。 ファイルシステム内のすべてのツリー (ROOT, CHUNK, EXTENT, FS, DEV, CSUM, UUID, FREE_SPACE) を再帰的に巡回し、エクステントツリーに METADATA_ITEM バック参照がないメタデータブロックを検出します。欠落しているすべてのバック参照を1つのトランザクションで注入し、「ルートツリーがコミット間で移動する」問題を回避します。

使用方法:

sudo ./scan_and_fix_all_backrefs /dev/sdX          # スキャンのみ
sudo ./scan_and_fix_all_backrefs /dev/sdX --write  # スキャン + 注入

2. fix_owner_refs.c

インライン TREE_BLOCK_REF 内の owner が、ブロックの実際の btrfs_header_owner() と一致しない場合に修正します。修復の失敗時にブロックがツリー間で再割り当てされると、不一致が発生します。

sudo ./fix_owner_refs /dev/sdX          # スキャン
sudo ./fix_owner_refs /dev/sdX --write  # 修正

3. fix_bad_levels.c

不正なレベルを持つ METADATA_ITEM および EXTENT_ITEM エントリを修正します。破損したレベル (例: 50, 55, 237) は、btrfs check --repair がループに入ったときに残されたゴミです。ブロックの実際の btrfs_header_level() と照合して検証します。

sudo ./fix_bad_levels /dev/sdX          # スキャン
sudo ./fix_bad_levels /dev/sdX --write  # 修正

4. fix_duplicate_extents.c

重複する METADATA_ITEM(同じ bytenr で異なるレベルのキー)を削除します。レベルが btrfs_header_level と一致する方を保持し、もう一方を削除します。

sudo ./fix_duplicate_extents /dev/sdX          # スキャン
sudo ./fix_duplicate_extents /dev/sdX --write  # 重複削除

5. remove_stale_ptrs.c

FS_TREE のすべてのレベル1ノードをスキャンします。3つのチェック(owner 不一致、first_key 不一致、または FS_TREE では無効なタイプ(例: BLOCK_GROUP_ITEM)の first_key)を使用して古い子ポインタを検出します。btrfs_del_ptr で削除します。

sudo ./remove_stale_ptrs /dev/sdX          # スキャン
sudo ./remove_stale_ptrs /dev/sdX --write  # 削除

6. fix_uuid_tree.c / fix_csum_tree.c

それぞれ UUID ツリー / CSUM ツリー用の空のリーフを作成します。ROOT_ITEM が別のツリーに再割り当てされたブロックを指している場合に便利です。カーネルは RW マウント時に自動的に UUID ツリーを再生成します。空の CSUM ツリーの場合、NODATASUM とフラグが立てられたファイルは検証に失敗しません。

sudo ./fix_uuid_tree /dev/sdX
sudo ./fix_csum_tree /dev/sdX

7. set_nodatasum.c

通常のファイル inode に BTRFS_INODE_NODATASUM フラグを設定します。csum ツリーが空でもファイルに期待されるチェックサムがある場合に使用します。これにより読み取りエラーが発生します。NODATASUM により、カーネルは checksum のルックアップをスキップします。

sudo ./set_nodatasum /dev/sdX          # スキャン
sudo ./set_nodatasum /dev/sdX --write  # 適用

8. fix_fstree_node.c

古いブロックのハードコードされたリストを持つバージョンです。これらを自動的に検出する remove_stale_ptrs を優先してください。削除する特定のブロックを手動で制御する必要がある場合にのみ使用してください。

9. add_backrefs.c

欠落しているバック参照のハードコードされたリストを持つ初期バージョンです。これらを自動的に検出する scan_and_fix_all_backrefs を優先してください。

セッション 2 のツールセット (2026-04-04/05): 大規模破損のための拡張リカバリ

上記のベースラインツールでは不十分だった場合 (プールに複数のツリーにまたがる 200K+ のエラーがある場合)、以下の追加ツールが作成されました:

scan_fstree_extents.c + scan_extent_tree.c

それぞれ FS_TREE と extent tree をウォークし、すべての参照/エクステントマッピングを含む TSV ファイルを生成する Pass 1 および Pass 2 スキャナーです。エクステントツリーをスクラッチから再構築する必要がある場合に、rebuild_extent_tree_apply への入力を作成するために使用されます。

rebuild_extent_tree_apply.c (ヘビーライター)

メインの Phase 3 ライターです。事前に折り畳まれた参照リスト(scan_fstree_extents + scan_extent_tree の差分から取得)を受け取り、トランザクションあたり 5000 チャンクで 300万+ の EXTENT_DATA_REF をエクステントツリーに注入します。DM-SMR の再シングルストールを避けるため、50K アイテムごとにスロットリングします。3× WD40EFAX SMR ディスク上で、約 34 分で 3,248,617 の挿入を成功させた実績があります。

sudo ./rebuild_extent_tree_apply /dev/sdX1 refs_folded.txt to_insert.txt watermark.txt --dryrun
sudo ./rebuild_extent_tree_apply /dev/sdX1 refs_folded.txt to_insert.txt watermark.txt --write

patch_block_group_used.c

Phase 3 ライターが既存の重複する file_extent_item のために特定の bg にオーバーシュートを残した場合に、BLOCK_GROUP_ITEM.used に対する外科的な単一フィールドパッチャーです。btrfs_update_block_group の space_info アカウンティング(ここでは不要)を避けるために、btrfs_set_block_group_used の直接セッターを使用します。flags & BTRFS_BLOCK_GROUP_DATA を事前検証します。

sudo ./patch_block_group_used /dev/sdX1 <bg_bytenr> <bg_length> <new_used> --write

remove_extent_items_by_key.c

エクステントツリーから (bytenr, num_bytes, expected_inode) EXTENT_ITEM のハードコードされたリストを削除します。RO マウントを妨げる単一のリーフ内の重複する古いエクステントをクリーンアップするために使用されます。削除前にアイテムごとのサニティチェック(inode 許可リストを含む 7 つの不変条件)を実行します。rebuilding_extent_tree=1 + reinit_extent_tree=true で実行し、space アカウンティングをスキップします(呼び出し側は patch_block_group_used で先に used をパッチします)。

clean_orphan_dir_entries.c

FS_TREE から孤立した DIR_ITEM + DIR_INDEX エントリをクリーンアップします。トランザクションあたり 100 エントリのチャンクで動作します。親 INODE_ITEM の i_size を更新します(namelen × 2 でデクリメント: 重大なバグ修正: v1 は namelen のみでデクリメントし、ディレクトリを無効な状態にしていました)。重要なトップレベルディレクトリ名(例: pelis, series, music, backups, homestorage)のハードコードされた除外リストがあります。i_size を raw namelen で決してデクリメントしないでください: BTRFS は namelen × 2 のアカウンティングを保存します。

clean_orphan_inode_refs.c

key.offset(親 inode)が孤立した親リストにある INODE_REF アイテムについて FS_TREE をウォークします。誤検出を避けるため、INODE_EXTREF はスキップします(EXTREF の key.offset はハッシュであり、親 ID ではありません)。トランザクションあたり 32 チャンクで動作します。

fix_dir_inode_counts.c

i_size = sum(name_len × 2) と nlink = 1 を、以前の孤立クリーンアップバグによってカウントが破損した DIR inode に対して再計算します。安全性のために極めて重要: いずれかの DIR が nlink = 2 の場合、そのパスに対する単一の rm -rf が数千のサブディレクトリを静かに削除します(rmdir 爆弾)。DIR_INDEX エントリをウォークし、ハッシュ衝突検出のために DIR_ITEM と相互参照します(経験的に 0 衝突が確認されています)。

remove_orphan_inode_subtrees.c

FS_TREE から孤立した inode サブツリー(DIR ファミリー + スタンドアロン REG)を削除します。ターゲットごとに: EXTENT_DATA, INODE_REF, INODE_EXTREF, XATTR、そして最後に INODE_ITEM をウォークして削除します。DIR ファミリーごとにトランザクション(サブツリーごとにアトミック)、スタンドアロン REG は 50 チャンクで動作します。ハードコードされたパラノイド除外リストがあります。

⚠️ 主要な安全性の注意: 以下の「Bulletproof subset criterion」を参照してください。

remove_stale_ptrs_v2.c

remove_stale_ptrs の改良版: parent expected_key を持つ空のリーフを検出し(v1 はこのケースをスキップ)、再帰的な 2 レベルスキャン(root→level1 + level1→leaves)、動的バッファ(512 制限なし)、read_tree_block の失敗を許容します。

insert_one_extent_poc.c

検証付きの単一エクステント挿入の PoC です。rebuild_extent_tree_apply を実行する前に API パスを検証するために使用されました。

Bulletproof subset criterion (CRITICAL)

2026-04-05 セッション中、remove_orphan_inode_subtrees は異なる理由で同じ BUG_ON アサーションで 2 回クラッシュしました:

クラッシュベクトル 1: MIXED リーフ (gen 3601、孤立した inode とライブ inode の両方を含む) 上の直接の btrfs_cow_block(leaf) → update_ref_for_cow が子をウォーク → 古い兄弟子に対する __btrfs_mod_ref(inc=1) → btrfs_free_extent(phantom) が -ENOENT を返す → BUG_ON → SIGABRT。

ツールをダウンロード