⬢ DragonFlyBSD Kernel Audit
DF-5538 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5538",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED + FIX VALIDATED. sys/platform/vkernel64/platform/copyio.c:165 (swapu32) and :229 (fuwordadd32) use the 64-bit twins page-straddle guard `PAGE_SIZE - (p & PAGE_MASK) < sizeof(uint64_t)` for 32-bit operations, so a 4-byte-aligned word at page offset 0xFFC (which fits entirely in-page) is spuriously rejected with the fault sentinel -1. Live via umtx_sleep(2) (kern_umtx.c:146/172/224 reads the word with fuwordadd32): inside a vkernel, a page-tail futex NEVER sleeps on a matching value (instant EBUSY, verified elapsed=0.000s vs control 1.460s at offset 0) and sleeps the FULL timeout on a phantom -1 that is not the words value (verified 0.300s sleep with word=0x41). Native pc64 reference with the identical binary: all probes correct. No memory unsafety (guard is over-strict, never under-strict); impact ceiling is broken userland synchronization inside a vkernel (lost wakeups / busy-fail / phantom sleeps). Applying fix.diff (sizeof(uint64_t) -> sizeof(uint32_t) at both sites), rebuilding VKERNEL64 and re-running the exact PoC: all probes pass (B sleeps 1.510s, C instant EBUSY, RESULT OK mask=0).",
  "exploit_chain": "",
  "evidence": "run.log (vkernel baseline: probe B off0xFFC EBUSY elapsed 0.000, probe C sleeps 0.300s on phantom -1, control A off0x000 OK; plus native pc64 reference run all-OK in build/run transcript), run.fixed.log (post-fix: B sleeps 1.510s, C instant EBUSY, VKPROBE_RC=0), fix-build.log (incremental rebuild NK_RC=0, copyio.o recompiled), fix.diff (two-line change), env.txt (guest uname + image md5)",
  "kernel_refs": [
    "sys/platform/vkernel64/platform/copyio.c:165",
    "sys/platform/vkernel64/platform/copyio.c:229",
    "sys/platform/vkernel64/platform/copyio.c:96",
    "sys/kern/kern_umtx.c:146",
    "sys/kern/kern_umtx.c:127",
    "sys/platform/pc64/x86_64/uwrapper.c:82"
  ],
  "poc_changes": "Seed had no code: wrote df5538.c from scratch (three umtx_sleep probes: page-offset-0 control, page-tail 0xFFC matching-value, page-tail 0xFFC sentinel-value, classified by elapsed time because DF umtx_sleep returns EAGAIN after sleeping out its timeout). Initial probe classification wrongly required rc==0 for slept \u2014 fixed to time-based classification after the native reference run revealed the EAGAIN-on-timeout convention. Run rig (build_kernel/image/run.sh) adapted from the proven DF-5337 vkernel rig.",
  "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": 1380,
  "guest_dirty": 1,
  "build_cmd": "cc -static -O2 -o /root/df5538 /root/df5538.c  (guest); cd /usr/src && make -j6 nativekernel KERNCONF=VKERNEL64 (vkernel kernel)",
  "run_cmd": "sh /root/run5538.sh  (boots /usr/obj/usr/src/sys/VKERNEL64/kernel.debug -m 512m -r /vkroot.img -n 2, runs /root/df5538 on the vkernel console); native reference: /root/df5538",
  "code_hash": "be43ea7fdd4baeb7a4d16b06e80b753fac2ffe464424ed93787be60f29e8f85c",
  "notes": "vkernel-only; host kernel pc64 path verified correct natively (same binary, all probes OK). swapu32 latent (no in-tree caller); casu32/casu64/swapu64/fuwordadd64 also caller-less. Guest /usr/src was patched for fix validation and the guest rebuilt VKERNEL64 \u2014 guest reset with-src performed before return per contract.",
  "recommended_fix": "copyio.c:165 and :229: change the 32-bit ops straddle guard from sizeof(uint64_t) to sizeof(uint32_t)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Baseline vkernel: probe B off0xFFC instant EBUSY (0.000s) and probe C slept 0.300s on phantom -1 (BROKEN mask=3). After applying fix.diff to guest /usr/src, incremental make nativekernel KERNCONF=VKERNEL64 (NK_RC=0), exact same PoC: probe B sleeps the full 1.510s (EAGAIN after sleep = word read correctly), probe C instant EBUSY, RESULT OK mask=0, VKPROBE_RC=0. Bad behavior gone; no regressions in control probe A.",
  "fix_evidence": "fix.diff; fix-build.log; run.fixed.log (post-fix console); run.log (baseline console)"
}