DragonFlyBSD Kernel Audit
DF-3049 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3049",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "s_desc_size is only validated when the 64BIT feature is set; ext2_gd_csum() otherwise reads s_desc_size-32 bytes from each fs->e2fs_gd[i], past the allocation. Demonstrated via the console-printed crc: kernel 'expected' values (0x7c2e, 0x3c11) vary with heap state and differ from the exact in-bounds computation (0x04e5) -> live kernel heap bytes entered the crc. 16-bit-per-mount oracle; rw unmount writes the crc to the attacker device.",
  "exploit_chain": "crafted metadata_csum (no 64BIT) image, desc_size=512, gds 0..62 re-checksummed offline, gd63 wrong -> mount -> ext2_gd_csum_verify prints expected=0xNNNN computed over 448 OOB heap bytes -> repeat with varying desc_size / heap churn -> solve crc32c linear system for adjacent-heap bytes (KASLR-defeat / heap disclosure, ~N/2 mounts for N bytes)",
  "evidence": "console_lines.txt (3 mounts, varying expected), run.log, craft.py output (offline in-bounds csum 0x04e5 == stored), fix_run.txt (fixed: EINVAL, no bad-gd print)",
  "kernel_refs": ["sys/vfs/ext2fs/ext2_vfsops.c:549", "sys/vfs/ext2fs/ext2_csum.c:684", "sys/vfs/ext2fs/ext2_csum.c:713", "sys/vfs/ext2fs/ext2_csum.c:716", "sys/vfs/ext2fs/ext2_csum.c:733", "sys/vfs/ext2fs/ext2_vfsops.c:1570"],
  "poc_changes": "crafted from scratch: 64-group 1K-block metadata_csum fs (512MB sparse), desc_size=512, sb crc32c recomputed, gd csums backward-solved for desc_size=512 semantics so the kernel reaches group 57/63 before failing; crc32c implemented to match calculate_crc32c (no inversions).",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 140,
  "guest_dirty": 0,
  "build_cmd": "python3 craft.py df3049.img ; cc -O2 -o /root/vntool /root/vntool.c",
  "run_cmd": "/root/vntool attach 0 /root/df3049.img; mount -t ext2fs -o ro /dev/vn0 /mnt/e2 (x3, with heap churn between)",
  "code_hash": "31924c7b19f16ce3319fed24739e5b3b7ea1502b643dd7bebff249d329126308",
  "notes": "first attempt failed at gd=56 due to a script-ordering bug (gd63 csum set after the backward solve) — fixed and re-run; the failure-at-56 artifact also confirmed the in-memory gd layout model. Leak rate limited (16 bits/mount) hence Medium despite certain OOB read.",
  "recommended_fix": "validate s_desc_size <= sizeof(struct ext2_gd) (E2FS_64BIT_GD_SIZE) in ext2_compute_sb_data() regardless of feature bits",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 (same kernel; ext2fs.ko rebuilt with fix.diff hunk 1, 2026-09-05)",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fixed module rejects the image with EINVAL at the desc_size bound before any gd checksum work; console shows no 'bad gd' line (no OOB read, no oracle).",
  "fix_evidence": "findings/poc/DF-3049/fix_run.txt; findings/poc/DF-3047/fix.diff (hunk 1)"
}