ichsmb_pci_attach requests 16 I/O-port bytes first while ICH5+ SMBus BARs decode 32 (64 under QEMU's ICH9) β on BIOS-unprogrammed BARs pci_alloc_map under-claims the decode window, leaving the tail bytes hardware-decoded but rman-unowned
Summary
The 16-first request ordering asks for half (or a quarter) of the fixed hardware decode of every ICH5+ part in the driver's own ID table: on firmware-programmed BARs the request is silently upgraded to the rl entry's full count (measured live: 16 asked -> 64 allocated), but when the BIOS left the BAR unprogrammed pci_add_map records no rl entry and the small count goes to pci_alloc_map - BAR+0x10..+0x1f stay decoded-by-SMBus but owned-by-nobody, so a later IOPORT allocation landing there aliases into SMBus register space. Root/config-triggered only, no in-tree claimant. Largest-first ordering fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5599 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.sh | β | 141 B | view raw | |
| run.log | β | 586 B | view raw | |
| env.txt | β | 570 B | view raw | |
| fix.diff | β | 550 B | view raw | |
| VERDICT.md | β | 2.8 KB | β raw | |
| README.md | β | 1.1 KB | β raw | |
| verdict.json | β | 3.5 KB | view raw |
DF-5599 β ichsmb IOPORT claim sizing vs ICH5+ BAR decode (Info, hardening)
File: sys/bus/smbus/ichsmb/ichsmb_pci.c (pass 2)
What this pack demonstrates
The driver requests 16 I/O-port bytes first (ichsmb_pci.c:233-234)
but ICH5+ SMBus BARs decode 32 (64 under QEMU's ICH9 model β
measured). On firmware-programmed BARs the newbus rl-count upgrade
rescues the request (measured: 16 asked β 64 allocated); on
BIOS-unprogrammed BARs (pci.c:2598-2610 records no rl entry β
pci.c:4058-4061 pci_alloc_map honors count=16) the tail of the
decode window stays hardware-decoded but rman-unowned.
Run (as root, inside the q35-rig guest with ichsmb+smb loaded)
sh run.sh
Expected output
bar [20] = type I/O Port, range 32, base 0x700, size 64, enabled
...
I/O ports:
0x700-0x73f
(64 bytes allocated for a 16-byte request β the ulmax upgrade of
subr_bus.c:2697-2700.)
Artifacts
run.sh, run.log, env.txt, fix.diff (32-first/16-fallback swap),
VERDICT.md (both code paths), manifest.json, verdict.json.
DF-5599 VERDICT β 16-first IOPORT claim under-claims ICH5+ SMBus BARs (Info)
Bottom line
not_reproduced / impact none / certain (mechanism measured, hazard
conditional). ichsmb_pci_attach asks for 16 I/O-port bytes first
(ichsmb_pci.c:233-234), falling back to 32 (:236-237). Every ID in the
driver's table from ICH5 (0x24d3) onward is an ICH5+ part whose SMBus
BAR decodes 32 bytes (Intel datasheet; QEMU's ICH9 model even decodes
64 β measured size 64 via pciconf -lb). Two paths:
- Path A β firmware-programmed BAR (this rig): the PCI enumeration
recorded a resource-list entry with the full BAR count
(
pci_add_map,pci.c:2551-2553sizing +:2620recording). The driver's default-window request(0, ~0, count=16)hitsresource_list_alloc's upgradecount = ulmax(count, rle->count)(subr_bus.c:2697-2700), so the rman reserves the full decode (measured: requested 16 β allocated0x700-0x73f= 64 bytes). No under-claim. Live-measured inrun.log. - Path B β BIOS-unprogrammed or BIOS-disabled BAR:
pci_add_mapdeliberately records no rl entry whenbase == 0or the BIOS wrote all-1s ("BIOS in an attempt to disable the resources",pci.c:2598-2610).pci_alloc_resourcethen routes the request topci_alloc_map(..., count=16)(pci.c:4058-4061), which reserves only 16 bytes and programs the BAR base β while the hardware's fixed decode mask still covers 32 (or 64) bytes. The tail (BAR+0x10 .. BAR+0x1f) is then decoded by the controller but owned by nobody in the global I/O rman: any later 16-byte IOPORT allocation that lands there aliases into SMBus register space (both devices respond; reads merge, writes side-effect). Classic under-claim hazard; root/config-triggered, no in-tree claimant exists on the standard rig β hence Info.
Path B could not be exercised on this guest without changing firmware behavior (the rl entry is built at boot from the programmed BAR; SeaBIOS on q35 always programs it), so the finding stands on the code path plus the measured path-A upgrade.
Fix
fix.diff β swap the order: request 32 first, 16 as the fallback
(largest documented decode first), so the pci_alloc_map path reserves
the full window on ICH5+ while pre-ICH5 16-byte BARs still attach via the
fallback. Info hardening; not kernel-rebuild-validated (fix_status=
not_testable) since no bad behavior is reproducible on the standard rig.
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_testableNo reproducible bad behavior on the standard rig (the programmed-BAR path is auto-upgraded and the unprogrammed path needs firmware changes to reach); fix.diff is a two-line order swap supplied for review.
fix.diff; run.log shows the measured upgrade that motivates keeping the request aligned with the rl count
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (pciconf -lb: 'bar [20] = type I/O Port, range 32, base 0x700, size 64, enabled' vs devinfo -r allocation 0x700-0x73f = 64 bytes for a 16-byte request); VERDICT.md (both code paths cited); run.sh
PoC changes
Measurement-only pack derived from the same rig boot; no seed PoC existed. The initially drafted 'under-claim always happens' framing was corrected after live measurement showed the subr_bus.c:2699 ulmax upgrade rescues the programmed-BAR case -- the finding was narrowed to the pci_alloc_map path, which is the honest residual.
Verified recommended fix
In ichsmb_pci_attach(), request 32 I/O bytes first and fall back to 16, so the firmware-unprogrammed path (pci_alloc_map) reserves the full ICH5+ decode window instead of leaving half of it decoded-but-unowned.
Verdict
ichsmb_pci_attach() requests 16 I/O-port bytes first with a 32-byte fallback (ichsmb_pci.c:233-237) although every device ID in the table from ICH5 (0x24d3) onward has an SMBus BAR that decodes 32 bytes (64 under QEMU's ICH9 model, measured). On a firmware-programmed BAR the default-window request is silently upgraded to the resource-list entry's full count (subr_bus.c:2697-2700, count = ulmax(count, rle->count)) -- live-measured on the q35 rig: requested 16, rman allocated 0x700-0x73f (64 bytes), so no under-claim manifests there. The hazard lives on the BIOS-unprogrammed/disabled-BAR path: pci_add_map deliberately records no rl entry when base==0 or the BIOS wrote all-1s (pci.c:2598-2610), so pci_alloc_resource routes the request to pci_alloc_map with count=16 (pci.c:4058-4061) and reserves only 16 bytes while the fixed hardware decode still covers the full 32/64-byte window -- the tail bytes are then decoded-by-SMBus but owned-by-nobody in the global I/O rman, and any later allocation landing there aliases into SMBus register space. Root/config-triggered, no in-tree claimant on the standard rig, not exercisable without changing firmware behavior: Info hardening. fix.diff swaps the request order to 32-first/16-fallback so the pci_alloc_map path always reserves the full window on ICH5+.
No comments yet.