DF-5700 / verdict.json
{ "finding_id": "DF-5700", "status": "reproduced", "reproduced": true, "impact": "none", "confidence": "certain", "verdict": "The by-design longword over-read of sys/libkern/bcmp.c is real and was measured on the pristine source inside the DFly guest: up to 7 bytes below the b2 start (down-align load at bcmp.c:81-85) and up to 7 bytes past either buffer end (streaming vb load at bcmp.c:89, tail loads at bcmp.c:110-111/128-129), exactly as the 1994 comment at bcmp.c:53-56 admits. The over-read is provably page-contained (every load is a naturally-aligned 8-byte load starting at an address holding >=1 in-bounds byte, so it can never straddle a page) \u2014 confirmed empirically by 512,496 guard-page-flanked calls with page-corner placements and zero faults \u2014 and the extra bytes are masked out of the result, so there is no disclosure and no reachable fault. Impact is none because the file is not compiled into any DragonFlyBSD kernel: sys/conf/files:2195-2237 omits it, sys/platform/pc64/conf/files:131 builds platform/pc64/x86_64/bcmp.s instead, and the running X86_64_GENERIC kernels bcmp (0xffffffff80bcb800, disasm in pack) is the mjg MEMCMP first/last-load implementation which never reads outside [b1,b1+len)/[b2,b2+len). This also corrects the DF-5676 premise: the shipped bcmp adds zero over-read to the libprop MATCH() chain (its cited bcmp.c:57-110 containment reasoning describes dead code). Latent hardening finding for any future platform that re-adds the file.", "exploit_chain": "", "evidence": "logs/instr.out (OVERREAD-CONFIRMED, max 7B below start / 7B past end, semantics 0 mismatches vs memcmp); logs/guard.out (RESULT: PASS - no load escaped the buffers valid pages, 12288+208+500000 cases); logs/kernel_bcmp_disasm.txt (shipped kernel bcmp = in-bounds asm; bcmp.o from bcmp.s, no libkern bcmp object); logs/fixed.out + logs/guardfix.out (fix validation: 0 out-of-region loads, 0 differential failures, guard sweep pass)", "kernel_refs": [ "sys/libkern/bcmp.c:53-56", "sys/libkern/bcmp.c:81-91", "sys/libkern/bcmp.c:100-111", "sys/libkern/bcmp.c:114-129", "sys/conf/files:2195-2237", "sys/platform/pc64/conf/files:131", "sys/platform/pc64/x86_64/bcmp.s:31", "sys/cpu/x86_64/include/asm_mjgmacros.h:49-198", "sys/libprop/prop_object.c:739" ], "poc_changes": "Original PoC plan used ASAN; the guest has no libasan (asan_harness.c retained, unbuildable there). Replaced with a transparent load-instrumented copy of the exact algorithm (bcmp_instr.c: every load site wrapped with address accounting, control flow identical, cross-checked 0 semantic mismatches vs memcmp) plus a PROT_NONE guard-page containment sweep. One harness self-bug (guard_harness memset could itself touch a guard page for large offsets) was checked and excluded by construction (fills stay within the usable page).", "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": 240, "guest_dirty": 0, "build_cmd": "cd findings/poc/DF-5700 && ./build.sh", "run_cmd": "cd findings/poc/DF-5700 && ./run.sh", "code_hash": "3e298e02725c5a9a1ed547284ed96e3c89825e1c4778ff00e1cea289af74a91f", "notes": "Dead-code status triple-proven: conf files, object list of the booted kernels build dir, and disassembly of the running kernels bcmp symbol. Answering the pass-2 checklist: (a) over-read ALWAYS same-page (aligned-load proof + 512k empirical cases); length==0 returns 0 without loads; (b) misaligned head/tail logic is CORRECT - 2,602,176 differential cases vs memcmp, 0 disagreements, return domain exactly {0,1}; (c) LE path returns 0/1; BE fallback returns truncated leftover length (subsumed by the int-length family, DF-5701); (d) nothing in this file can worsen DF-5676 - not compiled, and the compiled implementation adds zero over-read. Guest left running, untouched beyond /tmp scratch (cleaned).", "recommended_fix": "Replace the shifted-streaming body with provably in-bounds loads: align BOTH pointers bytewise, full-longword loop only while >= sizeof(long) bytes remain, bytewise tail (fix.diff; also fixes DF-5701 truncation).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff validated at rig level on the guest: instrumented out-of-region loads drop from 14,788 (max 7 B) to 0 (max 0 B); 2,304,192-case differential vs memcmp stays at 0 failures; 512k-case guard sweep still passes. Kernel rebuild validation not applicable: the file is not part of any DFly kernel build, so the rig compiles the exact source the kernel would compile if a platform re-added it.", "fix_evidence": "logs/fixed.out (fixed loads: below-start=0/0 past-end=0/0, RESULT: FIX-PASS), logs/guardfix.out (RESULT: PASS), fix.diff" } |