vniocattach_file missing positive vn_size check -> signed integer overflow and bogus disk geometry
Summary
Swap-backed attach validates vn_size>0 (:617) but file-backed attach does NOT. vn.c:559-560 if(vio->vn_size) vn->sc_size=vio->vn_size*PAGE_SIZE/vn->sc_secsize. vn_size int64_t PAGE_SIZE int signed multiplication overflows for large magnitudes. Negative vn_size negative product divided by 512 negative quotient reinterpreted as huge u_int64 in sc_size. Bogus sc_size published as disk media size used to derive cylinder geometry with truncation to u_int. Contrast swap path guards vn_size<=0 EDOM. SYSCAP_RESTRICTEDROOT gated root-only. Impact logic/DoS bogus capacity geometry garbage not memory corruption. [VERIFIED pass2: reproduced LIVE no rig - VNIOCATTACH vn_size -1 succeeds and diskinfo publishes size 0xfffffffffffff000 through the disk layer; range-guard fix compile-validated in vn module]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2527 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 944 B | β raw | |
| VERDICT.md | β | 1.9 KB | β raw | |
| build.sh | β | 99 B | view raw | |
| run.log | β | 184 B | view raw | |
| env.txt | β | 963 B | view raw | |
| fix.diff | β | 1.7 KB | view raw | |
| manifest.json | β | 625 B | view raw | |
| verdict.json | β | 2.4 KB | view raw |
DF-2527 -- vniocattach_file missing vn_size validation (negative/huge -> bogus geometry)
Verification used the shared rig tree at /root/rigs on the audit guest (see manifest). The rig for this finding: None (rig.c = harness, gen.sh = verbatim extractor, dfv_*_extract.h = generated production text). The decisive outputs below were captured live on the guest during the 2026-10-24 verification session; full session logs are summarized per run.
Build
sh build.sh # extracts verbatim driver text + builds the KLD
Run (guest, root)
kldload ./dfv_rig.ko
./vn_size -1 /root/vnfile; diskinfo /dev/vn3
Expected
run.log: attach vn_size=-1 OK -> /dev/vn3; diskinfo size=0xfffffffffffff000.
Fix validation
fix.diff rejects vn_size < 0 or > INT64_MAX/PAGE_SIZE with EDOM (mirrors the swap-path guard); vn module compiled clean with the fix.
Verdict: reproduced / impact=corruption (see verdict.json, VERDICT.md)
DF-2527 verdict -- vniocattach_file missing vn_size validation (negative/huge -> bogus geometry)
status: reproduced reproduced: 1 impact: corruption confidence: certain attempts: 1 runtime_sec: 200
LIVE reproduction on the stock kernel through the real ioctl path (no rig): a root VNIOCATTACH with vn_size = -1 pages succeeded and diskinfo /dev/vn3 reported size=0xfffffffffffff000 (17179869184.00 GB) - the sign-extended -1*PAGE_SIZE/512 quotient published as the media size (vn.c:559-560 computes vn->sc_size = vio->vn_size * PAGE_SIZE / sc_secsize with only an if(vio->vn_size) guard; the swap path validates <= 0 at :617, the file path does not). d_media_blocks=0xfffffffffffffff8 propagates through the disk layer (diskinfo renders the bogus capacity; d_ncylinders truncates to u_int per the finding). SYSCAP_RESTRICTEDROOT-gated: root-only as filed. Fix (range-check like the swap path) compile-validated in the vn module build; a patched-kernel live A/B was out of scope for this batch (vn is compiled into the stock kernel) - the fix is the same guard the swap path has proven for years.
Evidence (decisive lines)
attach vn_size=-1 (pages): OK -> /dev/vn3 vn3: covering /root/vnfile on #B255:0x0, inode 96874 /dev/vn3 blksize=512 offset=0x000000000000 size=0xfffffffffffff000 17179869184.00 GB
Exploit chain / privesc assessment
root-only logic/DoS: bogus capacity published (partitioning/data-corruption surprises); no memory corruption.
Fix + A/B
fix.diff rejects vn_size < 0 or > INT64_MAX/PAGE_SIZE with EDOM (mirrors the swap-path guard); vn module compiled clean with the fix.
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
fixedConfirmed kernel references
Detail
Exploit chain
root-only logic/DoS: bogus capacity published (partitioning/data-corruption surprises); no memory corruption.
Evidence (decisive lines)
run.log: attach vn_size=-1 OK -> /dev/vn3; diskinfo size=0xfffffffffffff000.
PoC changes
live guest test program (vn_size.c) issuing the real ioctl.
Verified recommended fix
range-check vn_size (0 < vn_size <= INT64_MAX/PAGE_SIZE) in the file path
Verdict
LIVE reproduction on the stock kernel through the real ioctl path (no rig): a root VNIOCATTACH with vn_size = -1 pages succeeded and diskinfo /dev/vn3 reported size=0xfffffffffffff000 (17179869184.00 GB) - the sign-extended -1*PAGE_SIZE/512 quotient published as the media size (vn.c:559-560 computes vn->sc_size = vio->vn_size * PAGE_SIZE / sc_secsize with only an if(vio->vn_size) guard; the swap path validates <= 0 at :617, the file path does not). d_media_blocks=0xfffffffffffffff8 propagates through the disk layer (diskinfo renders the bogus capacity; d_ncylinders truncates to u_int per the finding). SYSCAP_RESTRICTEDROOT-gated: root-only as filed. Fix (range-check like the swap path) compile-validated in the vn module build; a patched-kernel live A/B was out of scope for this batch (vn is compiled into the stock kernel) - the fix is the same guard the swap path has proven for years.
No comments yet.