ext2_balloc's four newb > UINT_MAX EFBIG returns leak the just-allocated block and leave ip->i_blocks inflated β permanent unprivileged-triggerable space/accounting corruption on 64BIT filesystems
Summary
At ext2_balloc.c:135-136, 169-170, 215-218 and 258-261, when ext2_alloc() succeeds but returns a block number above the 32-bit on-disk limit (possible only on an EXT2F_INCOMPAT_64BIT filesystem with data beyond block 2^32 - >=4TB at 1K blocks / >=16TB at 4K blocks), ext2_balloc returns EFBIG without calling ext2_blkfree() on newb. ext2_alloc() has already set the bitmap bit, decremented e2fs_fbcount/e2fs_gd nbfree, incremented the group counters and added btodb(e2fs_bsize) to ip->i_blocks - none rolled back. The block is marked allocated on media yet referenced by no inode - permanently lost space plus on-disk accounting drift until fsck. Any unpriv user with write access on such a fs triggers one leak per rejected allocation. Not reachable on 32-bit-count (REV0/classic) filesystems. Phase V skipped (Low; >4TB trigger environment unprovisionable on this guest). Fix: ext2_blkfree + i_blocks rollback before each EFBIG return (or teach ext2_alloc to reject >32-bit results up front). [VERIFIED pass2: 4TiB 64BIT ext2 unprovisionable on guest; four EFBIG leaks line-certain; fix compile-validated]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3234 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | β | 872 B | view raw | |
| README.md | β | 406 B | β raw | |
| VERDICT.md | β | 1.7 KB | β raw | |
| build.sh | β | 139 B | view raw | |
| run.sh | β | 88 B | view raw | |
| manifest.json | β | 561 B | view raw | |
| verdict.json | β | 1.4 KB | view raw | |
| fix.diff | β | 872 B | view raw | |
| env.txt | β | 272 B | view raw |
DF-3234 -- verification pack
Finding: ext2_balloc EFBIG paths leak the just-allocated block on 64BIT filesystems
Status: not_reproduced / impact corruption / confidence certain
What was run
n/a (needs >= 4TiB 64BIT ext2 volume)
How to reproduce
n/a
Expected
n/a
See VERDICT.md for the full narrative and verdict.json for the persisted machine verdict. Artifacts: fix.diff.
DF-3234 verification
Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64
Bottom line
Environment not provisionable on this guest: the trigger needs an EXT2_INCOMPAT_64BIT filesystem whose allocation returns blocks above 2^32 (>= 4 TiB at 1K blocks, >= 16 TiB at 4K blocks) - the four EFBIG returns in ext2_balloc fire only there, and each leaks the ext2_alloc result (bitmap bit set, group/free counters moved, i_blocks charged, nothing rolled back, no ext2_blkfree). The defect is line-certain by inspection (contrast the bwrite-failure path at :225 which does call ext2_blkfree), and the guest lacks both the disk space and an ext2 mkfs in base. Fix adds blkfree + unlock before each EFBIG return; compile-validated.
Kernel references
- sys/vfs/ext2fs/ext2_balloc.c:135-136
- sys/vfs/ext2fs/ext2_balloc.c:169-170
- sys/vfs/ext2fs/ext2_balloc.c:215-218
- sys/vfs/ext2fs/ext2_balloc.c:258-261
Exploit chain
(none: availability/correctness finding; no privilege chain)
Fix
ext2_blkfree + EXT2_UNLOCK before each EFBIG return
See fix.diff in this directory (git-apply-able against the read-only sys/ tree; applied only inside the disposable verification guest).
Reproduction
build: n/a (needs >= 4TiB 64BIT ext2 volume)
run: n/a
expected: n/a
Notes on the PoC (what changed vs the finding sketch)
(none)
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md walk over ext2_balloc.c:135-136/:169-170/:215-218/:258-261
Verified recommended fix
ext2_blkfree + EXT2_UNLOCK before each EFBIG return
Verdict
Environment not provisionable on this guest: the trigger needs an EXT2_INCOMPAT_64BIT filesystem whose allocation returns blocks above 2^32 (>= 4 TiB at 1K blocks, >= 16 TiB at 4K blocks) - the four EFBIG returns in ext2_balloc fire only there, and each leaks the ext2_alloc result (bitmap bit set, group/free counters moved, i_blocks charged, nothing rolled back, no ext2_blkfree). The defect is line-certain by inspection (contrast the bwrite-failure path at :225 which does call ext2_blkfree), and the guest lacks both the disk space and an ext2 mkfs in base. Fix adds blkfree + unlock before each EFBIG return; compile-validated.
No comments yet.