pccard_driver_added NULL-deref panic (pf->dev) after a CIS-error card, via kldload of any pccard client driver
Summary
attach_card bails on card.error with pf_head populated but pf->dev NULL for every function (children created only later); a subsequent devclass_add_driver (kldload any pccard client) runs driver_added which does device_get_state(pf->dev) raw-deref NULL. The sibling walk in detach_card guards exactly this condition; driver_added forgot. Root-gated (kldload). One-line-guard fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5357 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.5 KB | β raw | |
| VERDICT.md | β | 1.8 KB | β raw | |
| fix.diff | β | 377 B | view raw | |
| verdict.json | β | 2.4 KB | view raw | |
| manifest.json | β | 677 B | view raw |
DF-5357 β pccard_driver_added NULL-deref panic on kldload after a CIS-error card
What
pccard_driver_added() (sys/bus/pccard/pccard.c:1074-1103):
1081 STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
1082 if (STAILQ_EMPTY(&pf->cfe_head))
1083 continue;
1084 child = pf->dev;
1085 if (device_get_state(child) != DS_NOTPRESENT) /* child == NULL! */
pf->dev is NULL whenever pccard_attach_card() bailed out early β the
sc->card.error return at pccard.c:205-208 (e.g. CFTABLE "too many io/mem
spaces", memspace length 0/lengthsize 0 β pccard_cis.c:1047-1055,1167-1175,
1185-1203) or "Card has no functions" at pccard.c:209-212. Functions and
their cfe lists were already parsed into pf_head, but children are only
created further down (pccard.c:253-259).
device_get_state() is return(dev->state); (sys/kern/subr_bus.c:1824-1827)
β NULL + offsetof(struct device, state) dereference β kernel panic.
Trigger
- Insert a card whose CIS sets
card->error(many single-tuple ways, e.g. a CISTPL_CFTABLE_ENTRY with 5 io ranges after a valid CISTPL_CONFIG). kldloadany module registering a driver on the pccard bus (devclass_add_driverβbus_generic_driver_addedβpccard_driver_added).
kldload requires root, hence Low severity (root-triggered local panic / defense-in-depth). All in-tree pccard clients are compiled into GENERIC, so the realistic trigger is an out-of-tree or custom-built client module.
Fix
if (pf->dev == NULL) continue; before the state check β fix.diff.
DF-5357 VERDICT β pccard_driver_added NULL pf->dev dereference
Status: statically certain NULL-deref; trigger requires root (kldload), Low severity; not runnable in QEMU (no PCMCIA bridge)
Trace
- Card inserted with erroring CIS β
pccard_read_cispopulatessc->card.pf_head(functions + cfe chains) and incrementssc->card.error(sys/bus/pccard/pccard_cis.c:1053/1173/1188/1202). pccard_attach_cardreturns 1 atsys/bus/pccard/pccard.c:205-208before the child-creation loop atpccard.c:233-259β everypf->devremains NULL (functions areM_ZERO-allocated,pccard_cis.c:790-791/837-838).kldloadof a module with aDRIVER_MODULE(x, pccard, ...)βdevclass_add_driverβbus_generic_driver_addedβpccard_driver_added.pccard.c:1084-1085:child = pf->dev(NULL) βdevice_get_state(NULL)βreturn(dev->state);(sys/kern/subr_bus.c:1824-1827) β page-fault at offsetof(struct device, state) β panic.
The sibling walk in pccard_detach_card guards this exact condition
(if (pf->dev == NULL) continue;, pccard.c:304-305); pccard_driver_added
simply forgot it.
Impact
Local kernel panic; the triggering action (kldload) needs root, so this is hardening/robustness (Low), same class as DF-1489.
Not reproduced on guest
No PCMCIA bridge in QEMU β pf_head can never be non-empty on the guest;
static certainty only. Model adds nothing (single missing NULL check).
Fix
One-line guard (fix.diff), mirroring pccard.c:304-305.
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_testableOne-line NULL guard; cannot be boot-tested without PCMCIA hardware. Semantically identical to the existing guard in pccard_detach_card.
findings/poc/DF-5357/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md trace; fix.diff one-line guard mirroring pccard.c:304-305
PoC changes
No seed PoC; static pack (hardware+root trigger).
Verified recommended fix
Skip functions without a child device in pccard_driver_added (if (pf->dev == NULL) continue;), mirroring the pccard_detach_card guard at pccard.c:304-305.
Verdict
Statically certain NULL-deref panic, root-triggered (Low). pccard_attach_card returns early on card->error (sys/bus/pccard/pccard.c:205-208) after read_cis already populated pf_head, leaving pf->dev NULL for every function (children are only created at pccard.c:253-259). A later devclass_add_driver of any pccard-bus module (kldload) runs pccard_driver_added, which does child = pf->dev at pccard.c:1084 and passes it to device_get_state (pccard.c:1085) β device_get_state is a raw dev->state load (sys/kern/subr_bus.c:1824-1827), so NULL dereferences and the kernel panics. The sibling loop pccard_detach_card guards exactly this ('if (pf->dev == NULL) continue;', pccard.c:304-305). Not runnable in QEMU (no PCMCIA bridge): pf_head can never be populated on the guest, static evidence only.
No comments yet.