β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3832

trm_eepromBuf[unit] indexed by unbounded adapter unit β€” 128-byte OOB read+write of adjacent kernel globals at attach with a 5th Tekram card

Summary

NVRAMTYPE trm_eepromBuf[TRM_MAX_ADAPTER_NUM=4] is indexed by device_get_unit() at five sites with no bound check. unit=4 (5th adapter) makes NVRAM_trm_read_all store all 128 SEEPROM bytes through &trm_eepromBuf[4] - fully past the 512-byte array into adjacent .bss. Distinct from DF-2525 (u_long schema overflow inside a valid entry). Boot-time corruption of arbitrary adjacent kernel globals - requires 5+ physical Tekram PCI adapters. One-line reject fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3832 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.7 KB ↓ raw
VERDICT.md β€” 1.9 KB ↓ raw
verdict.json β€” 2.5 KB view raw
fix.diff β€” 489 B view raw
env.txt β€” 1.1 KB view raw
manifest.json β€” 602 B view raw

DF-3832 β€” trm_eepromBuf[unit] indexed by adapter unit with no TRM_MAX_ADAPTER_NUM bound β€” 128-byte OOB read+write of adjacent kernel globals at attach

  • File: sys/dev/disk/trm/trm.c (pass 2)
  • Class: CWE-787 out-of-bounds write (static global array), boot/attach-time
  • Severity: Low (requires 5 or more Tekram DC395 adapters in one machine β€” physical access)

Build / Run / Expected

Hardware-gated. On a machine with five Tekram DC395U/U2W PCI adapters, the 5th trm_attach (unit = 4) reads and writes trm_eepromBuf[4] β€” one entry past the end of the 4-entry global array β€” corrupting whatever linker-placed data follows it in .bss.

Root cause

  • NVRAMTYPE trm_eepromBuf[TRM_MAX_ADAPTER_NUM]; β€” trm.c:212, TRM_MAX_ADAPTER_NUM = 4 (trm.h:90). Each entry is 128 bytes (NVRAM_STRUC, trm.h:937-959).
  • trm_attach (trm.c:3549): int unit = device_get_unit(dev); β€” unbounded devclass unit.
  • trm_init(unit) β†’ trm_check_eeprom(&trm_eepromBuf[unit], pACB) β€” trm.c:3480 β€” and trm_initACB/trm_initDCB use &trm_eepromBuf[unit] again (trm.c:3066, 2925, 1112). None of these sites checks unit < TRM_MAX_ADAPTER_NUM.
  • Inside trm_check_eeprom, NVRAM_trm_read_all writes all 128 bytes read from the SEEPROM through *bpEeprom = NVRAM_trm_get_data(...) (trm.c:3181-3182) β€” so unit 4 writes 128 bytes past the array; the checksum-defaults path (trm.c:3289-3321) writes even more via the already-reported u_long bug DF-2525.

Distinct from DF-2525 (which is the u_long-vs-4-byte-schema overflow within the struct even for unit 0): this finding is the index bound β€” the wrong struct is selected out of bounds even with well-typed accesses.

VERDICT.md
↓ download raw

VERDICT β€” DF-3832

status: inconclusive (source-certain, hardware-gated) β€” reproduced: 0 β€” guest impact: none.

Index-site inventory (all use raw unit / AdapterUnit)

site expression
trm.c:3480 trm_check_eeprom(&trm_eepromBuf[unit], pACB)
trm.c:3066 pEEpromBuf = &trm_eepromBuf[unit]; (trm_initACB)
trm.c:2925 pEEpromBuf = &trm_eepromBuf[unit]; (trm_initDCB via unit param, also pACB->AdapterUnit from trm_action:573)
trm.c:1112 pEEpromBuf = &trm_eepromBuf[pACB->AdapterUnit]; (trm_ResetDevParam, ISR context)
trm.c:3332 pEEpromBuf = &trm_eepromBuf[unit]; (trm_initAdapter)

unit = device_get_unit(dev) (trm.c:3549) increments per attached trm device with no ceiling. trm_eepromBuf is NVRAMTYPE trm_eepromBuf[TRM_MAX_ADAPTER_NUM] (trm.c:212, TRM_MAX_ADAPTER_NUM=4 at trm.h:90); NVRAMTYPE is the 128-byte SEEPROM image (trm.h:937-959).

Write proof

trm_check_eeprom β†’ NVRAM_trm_read_all(pEEpromBuf, pACB) (trm.c:3279): for (bAddr = 0; bAddr < 128; bAddr++, bpEeprom++) *bpEeprom = NVRAM_trm_get_data(pACB, bAddr); (trm.c:3181-3182) β€” 128 bytes stored through &trm_eepromBuf[4] on the 5th adapter, i.e. fully past the 512-byte array. Checksum read (trm.c:3281-3284) reads the same OOB range first.

Guest

No Tekram PCI device (env.txt) β€” driver never attaches; not exercisable. Requires 5+ physical adapters β†’ Low severity, certain at source level.

Fix

trm_init: reject unit >= TRM_MAX_ADAPTER_NUM before the first dereference (fix.diff; git apply --check passes).

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Requires 5+ physical Tekram adapters for both baseline and patched runs; impossible on the audit guest. fix.diff is git-apply-able (verified).

fix.diff
↓ fix.diffper-fix-DF-3832

Confirmed kernel references

Detail

Exploit chain

physical: install 5+ DC395 adapters -> 5th attach writes 128 bytes of SEEPROM-derived data past trm_eepromBuf[] into adjacent kernel globals -> uncontrolled kernel-state corruption at boot.

Evidence (decisive lines)

README.md (all five index sites cited); env.txt; fix.diff (unit bound check in trm_init, git-apply --check passes)

PoC changes

PoC would need five physical Tekram PCI cards; pack is analysis + fix only.

Verified recommended fix

Reject unit >= TRM_MAX_ADAPTER_NUM in trm_init before any trm_eepromBuf[] dereference (fix.diff).

Verdict

trm_eepromBuf is a 4-entry global (TRM_MAX_ADAPTER_NUM, trm.h:90; trm.c:212) but is indexed by the unbounded devclass unit everywhere: trm_check_eeprom(&trm_eepromBuf[unit], ...) at trm.c:3480, trm_initACB at trm.c:3066, trm_initDCB at trm.c:2925 and trm_ResetDevParam at trm.c:1112. With five Tekram adapters attached, unit=4 selects storage one full NVRAMTYPE (128 bytes) past the array: NVRAM_trm_read_all then writes all 128 SEEPROM bytes through the out-of-range pointer (trm.c:3181-3182), the checksum loop reads 128 bytes (trm.c:3281-3284), and the defaults path writes further β€” a boot-time corruption of whatever .bss data follows trm_eepromBuf. Distinct from DF-2525 (that is the u_long/4-byte schema overflow inside a valid entry); this is the missing index bound. Not exercisable on the audit guest (a single-adapter QEMU has no Tekram HBA at all, env.txt); requires 5+ physical adapters, hence severity Low.