⬢ DragonFlyBSD Kernel Audit
DF-4661 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4661",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "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": 3,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df2413 && sh build.sh",
  "code_hash": "649368a4f0ba8c2b3e06ce44e4570d0ca199c48de7f40bd49afefb09bcc22a81",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Validated on the guest: fixA+B+C applied to a copy of the pristine ar2413.c, function bodies re-extracted verbatim from the patched copy, harness rebuilt and re-run. Baseline reproduces the defect; patched build shows the defect GONE (mode 1: no overflow / mode 2: early return, sentinel minPower, no wild-read propagation / mode 3: completes without the wild-address SIGSEGV). fix.diff is git-apply-able against the pristine tree (git apply --check clean) and was never applied to sys/.",
  "fix_evidence": "fix_run.log (full patched 3-mode run) vs run.log (baseline); fix.diff in pack; PATCHES_APPLIED + FIXED_BUILD_OK in fix_run.log.",
  "verdict": "REPRODUCED on the DragonFly guest (verbatim-extraction harness, mode 2): with an EEPROM-shaped zero-gain dataset (xpd_mask=0 -> all numVpd=0, the exact shape ar2413SetupRawDataset produces at ah_eeprom_v3.c:656-673) the functions backfill loops index with uint32 counters at 0: pPdGainBoundaries[ii-1] (ar2413.c:484) and pPDADCValues[kk-1] (ar2413.c:488) wrap to element index 0xFFFFFFFF and read at array+0x1FFFFFFFE bytes (+8.59 GB) -- the direct-map survival case proven by mapping the exact wild pages and observing both 0x5A5A values propagate into gainBoundaries[0] (-> AR_PHY_TPCRG5 by ar2413SetPowerTable:595-600) and pcdacTable[0] (-> 32 PHY reg writes, ar2413.c:586-593); the identical wrap arithmetic proven to fault in mode 3 (SIGSEGV si_addr == expected wild address). Plus uninitialized-stack read of Pmin_t2[0] at ar2413.c:424 (minPower varies run-to-run: 0xd2e0/0xd3b0/0xd620/0xd370). In-kernel this is a wild KVA read -> panic (KVA hole) or garbage radio programming; HALASSERT(:536) is compiled out in release and the caller (:533-535) never checks the return. Twin of DF-4620 (ar5413) / DF-4649 (ar2316). Fix validated (early return + caller check): no wild reads, no uninit read.",
  "exploit_chain": "crafted v3 EEPROM (xpd_mask=0) on AR2413 card -> numPdGainsUsed==0 -> uint32-wrapped wild reads at gb+0x1FFFFFFFE and pcdacTable+0x1FFFFFFFE (direct-map garbage or KVA-hole panic) + uninit Pmin_t2[0] stack read -> garbage TPCRG5/pdadc programming or kernel panic. No uid0 route.",
  "evidence": "run.log mode 2: gainBoundaries[0] = 0x5a5a, pcdacTable[0] = 0x5a5a, DF-4661 REPRODUCED; repeat section: minPower 0xd3b0/0xd620/0xd370 (uninit variance); fix_run.log patched mode 2: ret=0, sentinel minPower 0x7c7c, no propagation.",
  "kernel_refs": [
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:424",
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:484",
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:488",
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:533",
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:536",
    "sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:579",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:656",
    "sys/dev/netif/ath/ath_hal/ah_internal.h:665"
  ],
  "poc_changes": "Same harness as DF-4660 (mode 2); no kernel-code changes.",
  "notes": "Same uint32-underflow class also occurs at ar2413.c:464-465 on a different trigger (flat curves) -- filed as DF-4662; distinct root cause and guard from known DF-1796 (numChannels==0, pass 1, NOT re-reported).",
  "recommended_fix": "Early-return 0 when numPdGainsUsed==0 before the Pmin_t2[0] read, plus a caller-side numPdGainsUsed==0 -> AH_FALSE check in ar2413SetPowerTable (fix.diff).",
  "run_cmd": "./ar2413_harness 2",
  "attempts": 1
}