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)
PoC verification
Evidence pack
findings/poc/DF-3832 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 β andtrm_initACB/trm_initDCBuse&trm_eepromBuf[unit]again (trm.c:3066, 2925, 1112). None of these sites checksunit < TRM_MAX_ADAPTER_NUM.- Inside
trm_check_eeprom,NVRAM_trm_read_allwrites 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 β 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_testableRequires 5+ physical Tekram adapters for both baseline and patched runs; impossible on the audit guest. fix.diff is git-apply-able (verified).
fix.diff
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.
No comments yet.