⬢ DragonFlyBSD Kernel Audit
DF-4207 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4207",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Reproduced via source-faithful harness on the audit guest: with a 5112-layout (EEP_MAP 1) EEPROM whose ee_xgain[mode] nibble is 0, eepromExpandPower5112() (verbatim kernel code, sha256-gated extraction from the guests /usr/src) uses its 0xDEAD sentinel xgainList[0] as the pDataPerXPD[] index and writes 18 EEPROM-chosen bytes at pDataPerChannel+4+0xDEAD*20 (~1.09 MiB past a ~92-byte heap allocation), once per calibration pier at an 84-byte stride. In-kernel trigger is hardware-gated (requires an AR5212-family NIC with blanked/malicious EEPROM; the QEMU guest has no ath hardware), so on-guest impact is none \u2014 same classification as sibling DF-1447. fix.diff (missing kk==0 guard) validated with the same harness: zero OOB writes, clean AH_FALSE.",
  "exploit_chain": "EEPROM control (malicious/spoofed NIC or corrupted EEPROM) -> ath_hal_legacyEepromAttach at probe/module-load -> eepromExpandPower5112 wild heap write (semi-controlled 16-bit values, ~1.14MB offset, repeatable per mode/pier) -> heap corruption; panic/DoS realistic, uid0 chain not pursued (hardware-gated primitive, no leak-free grooming control demonstrated)",
  "evidence": "run.log lines damaged bytes past allocation: 18 (first at pDataPerChannel+1140106) and the wild-site hexdump 04 00 2a 00 3f 00 49 00 4e 00 2c 00 30 00 34 00 38 00 (all EEPROM-chosen); trigger_fixed run in the same log shows 0 damaged bytes and exit 0",
  "kernel_refs": [
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:192",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:197",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:225",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:227",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:229",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:381",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.c:1267",
    "sys/dev/netif/ath/ath_hal/ah_eeprom_v3.h:243"
  ],
  "poc_changes": "Original sketch had no working harness; built sha256-gated verbatim extraction of eepromAllocExpnPower5112/eepromExpandPower5112 + 5112 typedefs from the guests own /usr/src, shimmed allocator onto a 4 MiB canaried arena, fixed assembly ordering (defines before typedefs, storage after structs), regenerated malformed fix.diff with diff -u (git-apply verified), made build.sh PACK absolute and mirror the a/ tree layout for patch -p1.",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 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": 9,
  "guest_dirty": 0,
  "build_cmd": "cd findings/poc/DF-4207 && ./build.sh",
  "run_cmd": "cd findings/poc/DF-4207 && ./run.sh",
  "code_hash": "f40f669acf80d4e8cabbf473d3a2793058a6139315fcae2d59bd12022753684f",
  "notes": "Hardware-gated: needs AR5212-family NIC with EEPROM xgain nibble 0 for a mode with >=1 cal pier; no software-only trigger. Same-file sibling DF-1447 (wordsForPdgains[-1], 2413 path) is the index-family twin on the eepMap==2 path; this is the eepMap==1 path with a far more powerful primitive (wild write, not OOB read of a static table).",
  "recommended_fix": "In eepromExpandPower5112, reject xpdMask with no set bits (kk == 0) exactly like the existing kk > 1 rejection; long term also sanity-check ee_xgain[] nibbles at readHeaderInfo time.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (kk==0 guard) applied to the verbatim extraction: eepromExpandPower5112 returns AH_FALSE, 0 canary-damaged bytes, exit 0 \u2014 wild write eliminated. git apply --check clean against sys/; never applied to the read-only tree.",
  "fix_evidence": "run.log ===== with fix.diff applied ===== section: damaged bytes past allocation: 0 both runs, PASS: wild OOB write was NOT observed, RESULT: bug reproduced on stock, GONE with fix"
}