Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
btrfs_fixes — 심각한 익스텐트 트리 손상용 사용자 정의 BTRFS 복구 도구 (btrfs check --repair가 세그폴트, 루프, 또는 데드락으로 실패하는 경우) | Kitploit
도구/GitHubGitHub/msedek/btrfs_fixes
Vulnerability AnalysisForensicsData RecoveryPapers & ResearchLearning & Education
GitHubmsedek/btrfs_fixes

btrfs_fixes

심각한 익스텐트 트리 손상용 사용자 정의 BTRFS 복구 도구 (btrfs check --repair가 세그폴트, 루프, 또는 데드락으로 실패하는 경우)

저장소 보기
9165개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

btrfs_fixes: 사용자 정의 BTRFS 복구 도구

네이티브 명령어(btrfs check --repair, --init-extent-tree 등)로 복구할 수 없었던 심각한 익스텐트 트리 손상이 있는 12TB 멀티 디바이스 BTRFS 풀 복구 중에 작성된 사용자 정의 도구입니다.

복구의 구조화된 사례 연구, 근본 원인 분류, 그리고 이러한 도구의 대부분이 필요하지 않게 했을 상류 btrfs-progs 개선을 위한 건설적인 제안 모음을 보려면 **INCIDENT-ANALYSIS.md**를 참조하십시오.

이 도구를 사용해야 하는 경우

btrfs check --repair가 세그폴트를 일으키거나, 무한 루프에 빠지거나, 파일 시스템을 이전보다 더 나쁜 상태로 만드는 경우에만 이 도구를 사용하십시오.

도움이 되는 것으로 문서화된 사례:

  • btrfs check --repair가 [3/8] checking extents에서 세그폴트 (이슈 #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는 옵트인).
  • 이 도구를 실행할 때 파일 시스템은 마운트 해제되어 있어야 합니다.
  • btrfs-progs v6.19.1 이상이 필요하며, EEXIST 패치가 적용되어 있어야 합니다.

빌드

도구는 내부 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 백레퍼가 누락된 메타데이터 블록을 감지합니다. 단일 트랜잭션에서 누락된 모든 백레퍼를 주입하여 '루트 트리가 커밋 사이에 이동하는' 문제를 방지합니다.

사용법:

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 노드를 스캔합니다. 세 가지 검사(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이 설정되면 커널이 csum 조회를 건너뜁니다.

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와 익스텐트 트리를 탐색하여 모든 참조/익스텐트 매핑을 TSV 파일로 생성하는 패스 1 및 패스 2 스캐너입니다. 익스텐트 트리를 처음부터 다시 빌드해야 할 때 rebuild_extent_tree_apply의 입력을 구축하는 데 사용됩니다.

rebuild_extent_tree_apply.c (무거운 기록기)

주요 페이즈 3 기록기입니다. 사전 병합된 참조 목록(scan_fstree_extents + scan_extent_tree 비교 결과)을 가져와 트랜잭션당 5000개씩 묶어 3M+ 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

페이즈 3 기록기가 기존 중복 file_extent_items로 인해 특정 bg에 초과 사용량을 남겼을 때 BLOCK_GROUP_ITEM.used를 외과적으로 단일 필드 패치하는 도구입니다. btrfs_update_block_group 공간 정보 계정(여기서는 원하지 않음)을 피하기 위해 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로 실행하여 공간 계정을 건너뜁니다(호출자가 먼저 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만 감소시켜 디렉토리를 잘못된 상태로 남겼습니다). 중요한 최상위 디렉토리 이름(e.g. pelis, series, music, backups, homestorage)에 대한 하드코딩된 제외 목록이 있습니다. 절대 i_size를 원시 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

이전 고아 정리 버그로 인해 개수가 손상된 DIR inode에 대해 i_size = sum(name_len × 2) 및 nlink = 1을 다시 계산합니다. 안전에 매우 중요: 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개씩 청크로 처리합니다. 하드코딩된 편집증적 제외 목록이 있습니다.

⚠️ 주요 안전 주의사항: 아래 "무적 부분 집합 기준"을 참조하십시오.

remove_stale_ptrs_v2.c

remove_stale_ptrs의 개선된 버전: parent expected_key가 있는 빈 리프를 감지합니다(v1은 이 경우를 건너뜀), 재귀적 2레벨 스캔(루트→레벨1 + 레벨1→리프), 동적 버퍼(512 제한 없음), read_tree_block 실패를 허용합니다.

insert_one_extent_poc.c

검증이 포함된 단일 익스텐트 삽입을 위한 개념 증명입니다. rebuild_extent_tree_apply를 실행하기 전에 API 경로를 검증하는 데 사용됩니다.

무적 부분 집합 기준 (매우 중요)

2026-04-05 세션에서 remove_orphan_inode_subtrees가 동일한 BUG_ON 어설션에서 서로 다른 두 가지 이유로 두 번 충돌했습니다:

충돌 벡터 1: 혼합 리프(세대 3601, 고아 및 활성 inode 모두 포함)에서 직접 btrfs_cow_block(leaf) → update_ref_for_cow가 자식 탐색 → 오래된 형제 자식에 대해 __btrfs_mod_ref(inc=1) → btrfs_free_extent(phantom)이 -ENOENT 반환 → BUG_ON → SIGABRT.

도구 다운로드