{
  "finding_id": "DF-2255",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Reproduced through the byte-identical real parse code compiled into the guest kernel: an EEPROM block header with length 2043..2047 (11-bit field, guard dead under ifdef DONTUSE) drives ar9300_calibration_data_read_array to write 4+length+2 = 2049..2053 bytes into u_int8_t word[2048] on the kernel stack, placing 1..5 fully attacker-controlled bytes past word[2047] (serial log shows e0 e1 e2 e3 e4 there with sentinel intact at 2053+, and a two-run diff tracking exactly +2048..+2052). On 4KB EEPROM cards every read succeeds so the overflow always fires; the 16-bit additive checksum gate is attacker-computable (chk case passes it and applies a payload). On this gcc8 -fno-stack-protector layout the bytes land on intra-frame slack (no panic observed); on SSP kernels the write smashes canary bytes = reliable attach-time panic. Input is on-card EEPROM/OTP content: attacker is a malicious/defective AR9300 peripheral or already-root (HAL_DIAG_EEWRITE on ATH_DIAGAPI builds) - no unprivileged local path exists, so realistic ceiling is hardware-triggered local DoS with a precise 1-5 byte stack write primitive. fix.diff (live bound check length > 2042 replacing the ifdef DONTUSE guard) validated on a rebuilt kernel: all five lengths leave word[2048..2052] sentinel-intact, diff tracks 0 OOB bytes, legitimate _compress_block path still restores 16/16 marker bytes, and DF-2256 remains live under the single fix (differential).",
  "exploit_chain": "",
  "evidence": "run.log (baseline kernel serial console): five *** OOB WRITE CONFIRMED *** lines for len 2043..2047 with word[2048..2052] = e0 e1 e2 e3 e4 preceded by in-bounds payload and followed by untouched 0xA5 sentinel; diff case moves exactly +2048..+2052 when only those EEPROM bytes change; chk case shows attacker-computed checksum passes and payload applied (DF2255-PWNED-OK!, 16/16). logs/run_fix1.log + fix_run.log: same triggers after fix.diff -> sentinel intact -- FIX EFFECTIVE x5, diff 0 tracked OOB bytes, chk still 16/16. logs/extract_baseline.log: sha256 gate 75771111... byte-identical extraction + ifdef DONTUSE liveness probe. env.txt: kernel/boot mapping.",
  "kernel_refs": [
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:3892",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:3848",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:3915",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:3922",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:3616",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c:4186",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h:41",
    "sys/contrib/dev/ath/ath_hal/ar9300/ar9300eep.h:99"
  ],
  "poc_changes": "Authored the whole rig for this verify run (no runnable seed existed): marker-based sha256-gated extractor, kernel-compiled harness with fake 4KB/2KB EEPROM device and sentinel stack window, sysctl trigger, three-kernel validation matrix. Iterations needed: kernel include fixes (string.h -> sys/libkern.h), -Wmissing-prototypes prototypes, symbol aliasing to avoid link collision with in-kernel ath_hal, PROBE_WIN 8192 with dump-safe scan limit, iteration-1 header replant so the crafted signature survives the parse walk, payload-pattern signature fallback plus last-known-offset fallback (6080) for fixed-kernel runs.",
  "attempts": 8,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #9: Sat Oct 17 17:54:41 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline evidence on kernel #6 17:43:48, fix1 on #7/#8, both-fixes on #9; see env.txt)",
  "runtime_sec": 3900,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df2255 && sh build.sh  (extract.sh sha256-gated byte-identical extraction; cp df2255_harness.c df2255_verbatim.inc /usr/src/sys/kern/; printf kern/df2255_harness.c\\tstandard >> /usr/src/sys/conf/files; cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel KERNCONF=X86_64_GENERIC; fix validation via make -j6 quickkernel)",
  "run_cmd": "sysctl -w kern.df2255.rig=ovfall ; sysctl -w kern.df2255.rig=diff ; sysctl -w kern.df2255.rig=chk ; dmesg | grep DFH:   (root, in-guest; full battery in run.sh)",
  "code_hash": "53682c234e17482afc91927d7d896297b2f5080371d0d22298f237e8dfcec887",
  "notes": "CONTRIB vendored QCA HAL - upstream owns the fix; FreeBSD head 2026-10-17 still ships the dead ifdef DONTUSE guard (logs/freebsd_head_ar9300_eeprom.c line 3971), so fix.diff is a novel upstream-contributable patch. No unprivileged-local attack path (input = card EEPROM); no panic on this layout (bytes hit intra-frame slack; SSP kernels would smash canary -> panic). No uid0 chain exists for this input class - impact recorded as dos with the write primitive fully characterized. DF-2256 amplifies this bug (stale word[0..3] synthesize length on unreadable devices).",
  "recommended_fix": "Replace the ifdef DONTUSE-disabled length >= 1024 guard with a live check skipping blocks whose length > MOUTPUT - compression_header_length - compression_checksum_length (2042) before the read into word[MOUTPUT]."
}
