⬢ DragonFlyBSD Kernel Audit
DF-4520 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4520",
  "poc_id": "DF-4520",
  "status": "untested",
  "reproduced": 0,
  "impact": "none demonstrated (latent OOB kernel heap read + OS_MEMZERO OOB write at driver attach if the NIC EEPROM encodes MAXQCU>10; crafted/corrupted EEPROM = physical-card trust boundary)",
  "confidence": "speculative",
  "attempts": 0,
  "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",
  "code_hash": null,
  "exploit_chain": [],
  "evidence": "AR_EEP_MAXQCU returns MS(ee->ee_opCap, 0x01F0) = raw 5-bit 1..31 (ah_eeprom_v3.c:1640-1644, ah_eeprom_v3.h:72-73); ar5212_attach.c:862-865 assigns it to halTotalQueues unclamped; ah_txq is [HAL_NUM_TX_QUEUES=10] (ar5212.h:271, ah.h:236); ar5212_xmit.c:160-162 scans ah_txq[q] q<halTotalQueues, :177-183 OS_MEMZEROs &ah_txq[q] (HAL_TX_QUEUE_INACTIVE==0 so adjacent zeroed heap reads as free), :137/:144/:152 compute q=halTotalQueues-1/-2/-3. Fix clamp AH_MIN(val, HAL_NUM_TX_QUEUES) build-validated rc=0 -Werror (build.log:7145,13441,14897).",
  "kernel_refs": [
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:137",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:144",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:152",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:160",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:177",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_xmit.c:183",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212_attach.c:862",
    "sys/dev/netif/ath/ath_hal/ar5212/ar5212.h:271",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:1640",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.h:72"
  ],
  "verdict": "untested (runtime): halTotalQueues is a raw 5-bit EEPROM opcap field copied unclamped into the bound used for ah_txq[10] everywhere in ar5212_xmit.c; a crafted EEPROM (MAXQCU 11..31) makes ar5212SetupTxQueue read ah_txq[10..30] and OS_MEMZERO an out-of-bounds slot at attach. Real cards program <=10, so the trigger needs physical EEPROM tampering; no Atheros NIC exists on the guest. Source-confirmed; fix.diff clamps the cap and build-validated rc=0 -Werror.",
  "poc_changes": "n/a (no runtime PoC attempted; source-only confirmation per HW-gated protocol)",
  "notes": "ar5416_attach.c:957-959 has the identical unclamped AR_EEP_MAXQCU assignment (ar5416 HAL out of this files scope; flag for its own audit). Same latent class as DF-2201/DF-2073.",
  "recommended_fix": "Clamp pCap->halTotalQueues = AH_MIN(val, HAL_NUM_TX_QUEUES) at the single choke point in ar5212_attach.c (and mirror in ar5416_attach.c).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "build-only validation (runtime HW-gated): fix.diff applied to guest /usr/src; make nativekernel KERNCONF=X86_64_GENERIC rc=0 with -Werror; ar5212_attach.o rebuilt (build.log:7145,13441,14895-14897). Baseline/patched runtime not reproducible without an Atheros NIC with a crafted EEPROM.",
  "fix_evidence": "findings/poc/DF-4520/build.log (full untrimmed nativekernel log, BUILD_RC=0; decisive lines 3, 7145, 13441, 14895, 14897)",
  "build_cmd": "cd /usr/src && patch -p1 < /tmp/df4520_fix.diff && make nativekernel KERNCONF=X86_64_GENERIC",
  "run_cmd": "n/a (no Atheros NIC on guest; EEPROM-sourced trigger)"
}