⬢ DragonFlyBSD Kernel Audit
DF-3608 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3608",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "likely",
  "verdict": "Every address ncr(4) hands the 32-bit 53C8xx DMA engine is stored in a u_int32_t descriptor (scr_tblmove.addr ncrreg.h:306, struct link l_paddr, squeue[] ncr.c:1081) but sourced from unrestricted vtophys() results (nccb kmalloc ncr.c:6567/6577; CDB/sense of the CAM-allocated union ccb ncr.c:4094/4110; scatter segaddr ncr.c:6701; squeue insert ncr.c:4149). Only the script images are constrained below 4GB (kmem_alloc_contig 0..0xffffffff, ncr.c:3588-3605). On amd64 with RAM above 4GB the low 32 bits are programmed silently -> chip DMAs to wrong physical memory (corruption) or chases a garbage DSA. Runtime A/B on the audit guest (ncr0 live on QEMU lsi53c895a): -m 4096 -> attach OK, 12 selection attempts complete, queue handshake stalls; -m 6144 (only variable changed) -> attach + snooptest still OK (script images below 4GB) but ZERO chip progress, silent, no diagnostic. Behavioral delta corroborates the >4GB truncation; direct cross-memory corruption not observable because the emulator never lets this script reach a data phase. Structural defect certain from types; honest status inconclusive.",
  "exploit_chain": "",
  "evidence": "dmesg.4g.log (12x COMMAND FAILED + timeout stream) vs dmesg.6g.log (0 selections, same timeout stream only); VERDICT.md type-level trace; env.txt; run.log A/B narrative; fix.diff",
  "kernel_refs": [
    "sys/dev/disk/ncr/ncr.c:6567",
    "sys/dev/disk/ncr/ncr.c:6577",
    "sys/dev/disk/ncr/ncr.c:4149",
    "sys/dev/disk/ncr/ncr.c:4094",
    "sys/dev/disk/ncr/ncr.c:4110",
    "sys/dev/disk/ncr/ncr.c:6701",
    "sys/dev/disk/ncr/ncr.c:1081",
    "sys/dev/disk/ncr/ncr.c:3588",
    "sys/dev/disk/ncr/ncrreg.h:266",
    "sys/dev/disk/ncr/ncrreg.h:306"
  ],
  "poc_changes": "dropped nonexistent dev/disk/disk/disk_ioctl.h include; replaced <md5.h> (not present on guest) with an inline FNV-1a 64-bit checksum",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #2: Tue Sep 15 08:44:40 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 2820,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o ncr_dma32 ncr_dma32.c",
  "run_cmd": "./ncr_dma32 /dev/daN 8   (blocked: no da node appears on scbus2 because the chip never completes INQUIRY on the emulator at any RAM size)",
  "code_hash": "b100a0cf64960d6ec1aa2164ea0aef309d3c9a6b4aa1e52dce23291893f0e8c0",
  "notes": "A/B driver bring-up done on guest with rebuilt kernel (sym probe neutered so ncr claims QEMU lsi53c895a). dmesg legs archived as dmesg.4g.log / dmesg.6g.log. Guest reset to clean snapshot after the run.",
  "recommended_fix": "Constrain nccb allocation below 4GB (kmem_alloc_contig) and reject with CAM_REQ_TOO_BIG any transfer whose CDB/sense/scatter physical addresses do not fit in 32 bits instead of silently truncating",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored (nccb contig-alloc below 4GB + CAM_REQ_TOO_BIG rejection of unrepresentable CDB/sense/scatter addresses). Baseline data-phase I/O cannot be driven through the QEMU lsi emulator, so the patched-kernel A/B could not be run; not_testable.",
  "fix_evidence": "findings/poc/DF-3608/fix.diff"
}