ar5210Attach error path leaks HAL_EEPROM_v1 sub-allocation (missing ath_hal_eepromDetach)
- File:
sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c - Lines: 288β292 (leaky error path), 299β309 (correct detach for comparison)
- Severity: Low
- CVSS 3.1:
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U:C:N/I:N/A:L - CWE: CWE-401 Missing Release of Memory after Effective Lifetime
- Confidence: likely
- Status: new
Summary
When ar5210Attach fails after ath_hal_v1EepromAttach has succeeded β
most realistically because ath_hal_eepromGet(AR_EEP_MACADDR) rejects an
all-zero/all-ones MAC with HAL_EEBADMAC β the error path at
ar5210_attach.c:288-292 frees the outer ath_hal_5210 struct but never
releases the HAL_EEPROM_v1 object that v1EepromAttach malloc'd and
recorded in ah_eeprom.
The normal ar5210Detach (line 307) correctly calls ath_hal_eepromDetach
first; the attach error path is inconsistent and leaks ~200 bytes per failed
attach.
Root cause
ath_hal_v1EepromAttach (ah_eeprom_v1.c:180) allocates
ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1)), publishes it at
ah_eeprom_v1.c:245 (AH_PRIVATE(ah)->ah_eeprom = ee;) and registers the
detach hook at ah_eeprom_v1.c:247 (ah_eepromDetach = v1EepromDetach).
Back in ar5210Attach, the subsequent ath_hal_eepromGet(AR_EEP_MACADDR) call
(ar5210_attach.c:270) can fail: v1EepromGet (ah_eeprom_v1.c:35-54)
rejects a MAC whose 3-word sum is 0 or 0xffff*3 with HAL_EEBADMAC.
On that failure ar5210Attach executes goto eebad (line 274) β falls
through to bad: (line 290), which does if (ahp) ath_hal_free(ahp) (lines
291-292) but never invokes ath_hal_eepromDetach(ah).
The ath_hal_eepromDetach macro (ah_internal.h:474-477) is already
NULL-safe (if ah_eepromDetach != AH_NULL), so calling it on the paths where
v1EepromAttach was not reached is a no-op β the omission is simply an
oversight versus ar5210Detach:299-309 which does
ath_hal_eepromDetach(ah); ath_hal_free(ah);.
Threat model
Attacker position: local with the ability to present a malicious/faulty
AR5210 PCI/CardBus device whose EEPROM passes the magic (0x5aa5), version
(top nibble==1), and 64-word XOR checksum (==0xffff) gates β i.e. a device
that looks valid to v1EepromAttach β but whose MAC address words sum to 0
or 0xffff*3.
This is achievable with an EEPROM-programmed card, a CardBus/PCIe card with flashable EEPROM, or a QEMU-emulated device.
Each failed attach leaks one ~200-byte kernel malloc
(sizeof HAL_EEPROM_v1 β 159 bytes + allocator overhead).
Impact: bounded availability exhaustion. A failed attach means the NIC does not come up, and re-triggering requires device re-probe (physical re-insertion or privileged bus rescan), so the leak rate is low and amplification to memory exhaustion requires repeated reinsertion/rescan.
No confidentiality or integrity impact; no code-execution primitive.
Requires specific (faulty or malicious) hardware β hence Low.
Proof of concept
Hardware-triggered (no pure-userspace trigger exists for an attach-path bug).
Reproduce with a real AR5210 card plus an external EEPROM programmer, or a QEMU device model:
- Program the card EEPROM so that:
-
AR_EEPROM_MAGIC(offset 0x3d) =0x5aa5-AR_EEPROM_VERSION(offset 0xc1) top nibble =1- the 64 words atAR_EEPROM_ATHEROS_BASE(0xc0..0xff) XOR to0xffff-AR_EEPROM_REG_DOMAIN(0xbf) = any - the three MAC words atAR_EEPROM_MAC(0..2)(offsets 0x1f,0x1e,0x1d) are all0x0000(sum 0) - Insert/rescan the device so
if_ath.c:628 ath_hal_attach β ar5210Attachruns: -v1EepromAttachsucceeds andmalloc'see(ah_eeprom_v1.c:180) -AR_EEP_MACADDRreturnsHAL_EEBADMAC(ah_eeprom_v1.c:49-53) -ar5210Attachgoto eebad β badand freesahpwithout freeingee - Observe:
vmstat -m | grep ath(orkldstat/ kmemstats) shows oneath_hal_malloc'dHAL_EEPROM_v1block that is never reclaimed, growing by one per rescan/reinsert cycle.
Success criterion: persistent unreclaimed ~200-byte allocation after each failed attach.
A trivial QEMU variant: add a PCI device with vendor 0x168c / device
0x0007 whose EEPROM MMIO returns the crafted values above.
Recommended fix
Call ath_hal_eepromDetach(ah) before ath_hal_free(ahp) in the
ar5210Attach error path, mirroring ar5210Detach. The macro is NULL-safe
so it is correct for all paths that reach bad (no-op when v1EepromAttach
was not reached).
--- a/sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c
+++ b/sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c
@@ -288,8 +288,9 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh,
OS_REG_WRITE(ah, AR_PCICFG, pcicfg); /* disable EEPROM access */
bad:
- if (ahp)
- ath_hal_free(ahp);
+ if (ahp) {
+ ath_hal_eepromDetach(ah);
+ ath_hal_free(ahp);
+ }
if (status)
*status = ecode;
return AH_NULL;
References
sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:288-292β the leaky error pathsys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:299-309βar5210Detachcorrect patternsys/dev/netif/ath/ath_hal/ah_eeprom_v1.c:180,245,247βeeallocated, published, detach hook setsys/dev/netif/ath/ath_hal/ah_internal.h:474-477βath_hal_eepromDetachNULL-safe macro
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1995 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | Source verification narrative | 1.1 KB | β raw |
| fix.diff | suggested-fix | Fix: Call ath_hal_eepromDetach(ah) before ath_hal_free(ahp) in error path. | 456 B | view raw |
| build.sh | build-script | Build/validation instructions | 366 B | view raw |
| run.sh | run-script | Run instructions (HW-gated, source-only) | 184 B | view raw |
| env.txt | environment | Guest environment | 404 B | view raw |
DF-1995 - Source Verification
Verdict: REPRODUCED (source-only confirmation)
Finding: sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:290-292
Mechanism: ar5210Attach error path frees ahp via ath_hal_free without calling ath_hal_eepromDetach. HAL_EEPROM_v1 sub-allocation (~159 bytes) published at AH_PRIVATE->ah_eeprom is leaked.
Hardware dependency: Requires ath(4) ar5210 hardware.
Fix: Call ath_hal_eepromDetach(ah) before ath_hal_free(ahp) in error path.
Verification method
Source-only confirmation. The cited code path was traced line-by-line in the audited sys/ tree. The bug exists exactly as described. This is a HW-gated driver finding β the vulnerable code path requires specific hardware (GPU, controller, PHY, TPM, etc.) not present in the QEMU audit guest. Runtime reproduction on this guest is not possible without the hardware.
Fix validation
fix.diff authored and applied to guest source. All 40 fixes in this batch
compile cleanly in a single combined kernel build: make -j6 nativekernel
KERNCONF=X86_64_GENERIC β rc=0, zero -Werror violations.
Kernel: DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026
Fix verification
not_testablenot_testable: HW-gated. fix.diff applies + compiles in batch build (rc=0 -Werror). Source trace confirms fix closes the path.
Batch build: 40 fix.diffs applied, make nativekernel β rc=0 -Werror. Bug at sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:290-292 source-confirmed.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- n
- e
- t
- i
- f
- /
- a
- t
- h
- /
- a
- t
- h
- _
- h
- a
- l
- /
- a
- r
- 5
- 2
- 1
- 0
- /
- a
- r
- 5
- 2
- 1
- 0
- _
- a
- t
- t
- a
- c
- h
- .
- c
- :
- 2
- 9
- 0
- -
- 2
- 9
- 2
Detail
Exploit chain
none
Evidence (decisive lines)
Source trace sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:290-292. HW-gated (no HW in QEMU). Fix compiles in batch build rc=0.
PoC changes
Evidence pack: VERDICT.md, fix.diff, manifest.json. Fix: Error path frees ahp without eepromDetach β EEPROM sub-alloc leak. Call eepromDetach.
Verified recommended fix
See fix.diff. Error path frees ahp without eepromDetach β EEPROM sub-alloc leak. Call eepromDetach.
Verdict
REPRODUCED (source-only). sys/dev/netif/ath/ath_hal/ar5210/ar5210_attach.c:290-292: Error path frees ahp without eepromDetach β EEPROM sub-alloc leak. Call eepromDetach.
No comments yet.