DF-5599 / verdict.json
{ "finding_id": "DF-5599", "status": "not_reproduced", "reproduced": false, "impact": "none", "confidence": "certain", "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 QEMUs ICH9 model, measured). On a firmware-programmed BAR the default-window request is silently upgraded to the resource-list entrys 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+.", "exploit_chain": "", "evidence": "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", "kernel_refs": [ "sys/bus/smbus/ichsmb/ichsmb_pci.c:233", "sys/bus/smbus/ichsmb/ichsmb_pci.c:236", "sys/bus/pci/pci.c:2551", "sys/bus/pci/pci.c:2598", "sys/bus/pci/pci.c:4058", "sys/kern/subr_bus.c:2697" ], "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.", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 120, "guest_dirty": 0, "build_cmd": "(none - measurement only)", "run_cmd": "sh run.sh", "code_hash": "", "notes": "Checklist item (d) of the family sweep. The 16-first order is inherited from ancient FreeBSD; requesting the largest documented decode first (32) with 16 as fallback closes the pci_alloc_map under-claim for all ICH5+ IDs while preserving pre-ICH5 16-byte BARs. No security impact demonstrated; filed as Info hardening.", "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.", "fix_status": "not_testable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "No 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_evidence": "fix.diff; run.log shows the measured upgrade that motivates keeping the request aligned with the rl count" } |