iicsmb_intr panics the kernel on any iicbus event outside {INTR_GENERAL..INTR_NOACK} β one stray controller status code is a system-down failure
Summary
The event switch's default is panic() over externally-supplied controller event ints (iicbus_if.m imposes no producer bound). Rig-injected event 153 through the real dispatch (the same call pcfintr makes) -> 'panic: iicsmb_intr: unknown event (153)' -> DDB; kprintf+break fix validated (logs and returns, transaction completes, guest alive). Fault-isolation defect, not attacker-data-driven today.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5525 Β· 13 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.2 KB | β raw | |
| VERDICT.md | β | 1.9 KB | β raw | |
| df5521_rig.c | β | 7.9 KB | view raw | |
| df5521_poc.c | β | 6.8 KB | view raw | |
| build.sh | β | 83 B | view raw | |
| load_chain.sh | β | 294 B | view raw | |
| build.log | β | 5.4 KB | view raw | |
| env.txt | β | 980 B | view raw | |
| panic.txt | β | 654 B | view raw | |
| run.fixed.log | β | 586 B | view raw | |
| fix.diff | β | 245 B | view raw | |
| manifest.json | β | 624 B | view raw | |
| verdict.json | β | 2.9 KB | view raw |
DF-5525 β iicsmb_intr panics the kernel on any iicbus event outside
iicsmb_intr() (sys/bus/iicbus/iicsmb.c:242-243) ends its event switch with
panic("%s: unknown event (%d)!", __func__, event). Events are plain ints
produced by controller drivers through iicbus_intr() (iiconf.c:45-51, the
path every pcf-style ISR takes); any future or third-party controller that
reports a status code outside INTR_GENERAL..INTR_NOACK (0x1..0x7) takes the
whole system down instead of being logged and dropped.
Files
df5521_rig.c shared rig; hw.dfa.fire_event=N injects
iicbus_intr(iicbus0, N, &c) exactly like a controller ISR
(only while the bus owner is set, i.e. mid-transaction)
df5521_poc.c fireevent mode: child holds SMB_BREAD in flight while the
parent fires event 153 (0x99)
panic.txt baseline: panic: iicsmb_intr: unknown event (153)! with
the full backtrace through iicbus_intr -> sys___sysctl
run.fixed.log patched: kprintf + continue, guest alive
fix.diff panic -> kprintf+break
Reproduce
chain up (load_chain.sh); sysctl hw.dfa.rdelay=300; /root/df5521_poc fireevent # baseline: panic -> db> (serial console)
DF-5525 VERDICT β REPRODUCED (kernel panic from a controller-supplied event value; hardening fix validated)
The bug
iicsmb_intr() handles INTR_GENERAL/START/STOP/RECEIVE/TRANSMIT/NOACK/
ERROR and then (sys/bus/iicbus/iicsmb.c:242-243):
default:
panic("%s: unknown event (%d)!", __func__, event);
The event is an unvalidated int produced by whatever controller driver
sits under the iicbus and is delivered through the production interrupt
path (iicbus_intr() β IICBUS_INTR(sc->owner), iiconf.c:45-51).
iicbus_if.m defines no contract that pins producers to {1..7}; a
controller bug (or a new event added to one driver but not the bridge β
exactly how INTR_NOACK-style additions happen) turns one stray status code
into a full system panic. Fault isolation, not attacker-reachable data:
severity Info.
Verification
Baseline (stock modules, production chain up, owner held by an in-flight
SMB_BREAD): firing iicbus_intr(iicbus0, 153, &c) β the same call
pcfintr makes on 8 paths β produced:
panic: iicsmb_intr: unknown event (153)!
iicsmb_intr() at iicsmb_intr+0x67
dfa_fire_event_sysctl() at ...
sysctl_root ... userland_sysctl ... sys___sysctl
Debugger("panic") β db>
Fixed (panic β kprintf + break): iicsmb_intr: unknown event (153)!
is logged, iicbus_intr returned (no fault), the in-flight transaction
completes, /dev/smb0 remains, guest alive.
Fix
fix.diff: log-and-continue. (An upstream-grade alternative is
KASSERT under DEBUG discipline; the kprintf preserves diagnosability
without the system-down failure mode.)
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
fixedStock: 1/1 runs panic (iicsmb_intr: unknown event (153)!, DDB). Patched: 1/1 clean -- event logged, iicbus_intr returns, in-flight transaction completes, /dev/smb0 intact, guest alive. Validated as part of the combined fixed-module build shared with DF-5521/5522/5523.
panic.txt vs run.fixed.log; fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
panic.txt (decisive: panic string + full backtrace through the production iicbus_intr dispatch with sc->owner set); run.fixed.log (kprintf instead of panic, guest alive, /dev/smb0 intact); fix.diff
PoC changes
shared rig with DF-5521; hw.dfa.fire_event sysctl injects iicbus_intr() on the rig's iicbus child exactly as a controller ISR would
Verified recommended fix
Replace the panic in the default case with a kprintf + break (or KASSERT under a debug option). See fix.diff (validated live).
Verdict
REPRODUCED: iicsmb_intr's default case panics on any iicbus event outside {1..7} (iicsmb.c:242-243). The event int is produced by the controller driver under the bus and delivered through the production interrupt path (iicbus_intr -> IICBUS_INTR(sc->owner), iiconf.c:45-51) with no interface-level contract bounding it (iicbus_if.m). Injecting event 153 the way a controller ISR would (same call pcf's pcfintr makes on 8 paths) with the owner held by an in-flight SMB_BREAD: 'panic: iicsmb_intr: unknown event (153)!' with backtrace iicsmb_intr+0x67 <- dfa_fire_event_sysctl <- sysctl_root <- userland_sysctl <- sys___sysctl -> DDB. With the fix (kprintf + break): 'iicsmb_intr: unknown event (153)!' logged, iicbus_intr returns, transaction completes, guest alive. Fault-isolation/robustness defect reachable only via controller-driver code (not attacker data) => severity Info.
No comments yet.