⬢ DragonFlyBSD Kernel Audit
DF-4273 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4273",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "The validation gap is certain from code and its arithmetic was reproduced on the guest: tw_osli_fw_passthru() performs kmalloc(roundup2(buffer_length, sg_size_factor)) + copyin(buffer_length) + copyout(buffer_length) with no upper bound on the caller-supplied TW_UINT32 buffer_length (TW_CL_MAX_IO_SIZE/128KB is enforced only later, at bus_dmamap_load). A single ioctl can demand a multi-gigabyte M_WAITOK kernel allocation and copyin, and lengths >= 0xFFFFFE01 wrap roundup2() to 0, silently executing the firmware command with no data payload. The tempting heap-overflow reading (wrap producing a small nonzero allocation overrun by a huge copyin) is impossible: for power-of-two modulus y, (x + y-1) wraps into [0, y-1) and masks to exactly 0 - proven on-guest (0xFFFFFF01 -> kmalloc(0)). End-to-end impact could not be observed: /dev/twa0 is mode 0600 (root) and the QEMU guest has no 3ware 9000 HBA (vendor 0x13C1 absent from pciconf), and QEMU cannot emulate one. Upstream FreeBSD 13.0 carries the identical unbounded code.",
  "exploit_chain": "",
  "evidence": "run.log (arithmetic table: 0x7FFFFFFF -> kmalloc(0x80000000) unchecked; 0xFFFFFF01..0xFFFFFFFF -> kmalloc(0) no-payload path; /dev/twa0 ENOENT), env.txt (guest PCI inventory + uname), VERDICT.md (full derivation incl. the false-positive kill)",
  "kernel_refs": [
    "sys/dev/raid/twa/tw_osl_freebsd.c:927",
    "sys/dev/raid/twa/tw_osl_freebsd.c:930",
    "sys/dev/raid/twa/tw_osl_freebsd.c:933",
    "sys/dev/raid/twa/tw_osl_freebsd.c:1031",
    "sys/dev/raid/twa/tw_cl_ioctl.h:96",
    "sys/dev/raid/twa/tw_cl_share.h:72",
    "sys/sys/param.h:403",
    "sys/dev/raid/twa/tw_cl_fwif.h:174"
  ],
  "poc_changes": "n/a (finding originated in this run; harness written fresh, fixed a missing <unistd.h> include after first build)",
  "attempts": 2,
  "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": 90,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o /tmp/twa_roundup2_overflow /tmp/twa_roundup2_overflow.c",
  "run_cmd": "/tmp/twa_roundup2_overflow",
  "code_hash": "dccb6dd2ba25c72d9054ef3e6b2dd1259fa0001fd72998fe6836b2a304617f70",
  "notes": "Impact none = nothing observed at runtime (hardware absent); the filed severity (Low) covers the certain-by-code DoS/validation gap. /dev/twaN is 0600 root:operator (tw_osl_freebsd.c:405-407) so this is not an unpriv escalation path. The near-2^32 silent no-payload behavior is an additional correctness hazard (firmware command executed without its data). Guest left clean (no kernel changes, no panics).",
  "recommended_fix": "Reject buffer_length > TW_CL_MAX_IO_SIZE with E2BIG before any allocation in tw_osli_fw_passthru (see fix.diff)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored from line-accurate root cause; not build/boot-validated because the driver cannot attach on the audit guest (no 3ware hardware) and the bug itself was not runtime-reproduced there",
  "fix_evidence": "findings/poc/DF-4273/fix.diff (bound check inserted before tw_osli_get_request at tw_osl_freebsd.c:912)"
}