sn_attach() ignores sn_activate() failure: rman_get_cpuid(NULL) guaranteed kernel panic during attach, plus register writes into ISA DMA-controller ports 0x00-0x0F
Summary
sn_attach discards sn_activate's return (the probe path checks the identical call - the asymmetry). On any attach-time resource failure, port_res/irq_res are NULL and BASE is 0: the bank selects/revision/config/MAC writes all land inside the primary 8237 ISA DMA-controller register range, and ifq_set_cpuid(rman_get_cpuid(NULL)) dereferences NULL twice - guaranteed panic during DEVICE_ATTACH. Later sninit would scribble further over ports 0x00-0x0F. Propagate-the-error fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4354 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.5 KB | β raw | |
| VERDICT.md | β | 4.6 KB | β raw | |
| fix.diff | β | 229 B | view raw | |
| env.txt | β | 818 B | view raw | |
| verdict.json | β | 3.4 KB | view raw | |
| manifest.json | β | 1.1 KB | view raw |
DF-4354 β sn_attach() ignores sn_activate() failure β rman_get_cpuid(NULL) kernel panic + stray I/O to ISA DMA-controller ports
File: sys/dev/netif/sn/if_sn.c
Verdict status: untested β hardware-gated (SMC91xx ISA/PCMCIA NIC absent from the QEMU guest; driver is optional sn pccard-only module). Source-level certainty: certain.
Class: CWE-252 (unchecked return value) β CWE-476 (NULL pointer dereference in kernel) + stray port I/O.
Where
sys/dev/netif/sn/if_sn.c:164βsn_attach()callssn_activate(dev);and discards the return value.sys/dev/netif/sn/if_sn.c:1170-1192βsn_activate()returnsENOMEMwithsc->port_res == NULL,sc->irq_res == NULL, andsc->sn_io_addrnever assigned (newbus softc is allocated withM_ZERO, soBASE(sc->sn_io_addr, if_snreg.h:400) is 0).sys/dev/netif/sn/if_sn.c:173-188β with BASE=0 the attach path performsoutw(0x0E,3)(SMC_SELECT_BANK(3)),inw(0x0A)(REVISION),inw(0x00)(CONFIG), and β whenpccard_enaddris set βoutw(0x04/0x06/0x08, mac_word). Ports0x00-0x0Fare the primary 8237 ISA DMA controller registers (channel address/count + command/status), NOT this NIC.sys/dev/netif/sn/if_sn.c:216βifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->irq_res));withirq_res == NULL.rman_get_cpuidis((r)->r_rm->rm_cpuid)(sys/sys/rman.h:157) β a double dereference of NULL β guaranteed kernel panic during device attach.
Trigger
Any sn_activate() failure inside sn_attach(): I/O port range or IRQ that was allocatable during sn_probe() (which activates, then deactivates at if_sn.c:1318-1321) is no longer allocatable at attach time β resource conflict on the pccard CIS entry, IRQ claimed by another driver in the probeβattach window, or bus_setup_intr-adjacent resource exhaustion. The driver then proceeds to attach against NULL resources.
Fix
--- a/sys/dev/netif/sn/if_sn.c
+++ b/sys/dev/netif/sn/if_sn.c
@@ -161,7 +161,10 @@ sn_attach(device_t dev)
int j;
int error;
- sn_activate(dev);
+ error = sn_activate(dev);
+ if (error)
+ return (error);
snstop(sc);
Reproduce
Not runnable: the QEMU guest has no SMC 91xx hardware and the driver is a module
(sys/conf/files:1247 β dev/netif/sn/if_sn.c optional sn; front-end is pccard-only,
sys/dev/netif/sn/if_sn_pccard.c:106). Guest check performed and recorded in
env.txt (ifconfig -l shows only vtnet0 lo0; no sn module loaded; 0 SMC PCI
devices). Source-level proof is in VERDICT.md.
DF-4354 β VERDICT
Status: untested (hardware-gated) Β· Source-level confidence: certain Β· Expected on real hardware: kernel NULL-deref panic at device attach; collateral stray writes to ISA DMA-controller ports.
Root cause (path:line)
sn_attach()atsys/dev/netif/sn/if_sn.c:164invokessn_activate(dev)without checking the return value. Comparesn_probe()at if_sn.c:1236-1237, which does check it (if ((err = sn_activate(dev)) != 0) return err;).sn_activate()(if_sn.c:1166-1193) can fail after either resource allocation: -bus_alloc_resource(... SYS_RES_IOPORT ...)failure β returnsENOMEMat if_sn.c:1177 withsc->port_res == NULL; -bus_alloc_resource_any(... SYS_RES_IRQ ...)failure β returnsENOMEMat if_sn.c:1188 (port already released bysn_deactivate),sc->irq_res == NULL. In both casessc->sn_io_addris never written (if_sn.c:1191 is only reached on success). The newbus softc is zero-allocated (M_ZEROindevclass_alloc_device), soBASEmacro (sc->sn_io_addr,sys/dev/netif/sn/if_snreg.h:400) evaluates to 0.- Attach continues:
- if_sn.c:173
SMC_SELECT_BANK(3)βoutw(0x0E, 3)β port 0x0E is the ISA DMA controller (8237) write-request/chain-mask register; - if_sn.c:174rev = inw(0x0A)β reads DMA ch2 word count as "chip revision"; the value then feedschip_ids[(rev>>4)&0xF](the DF-1552 OOB-print issue, now reachable at attach with pure garbage); - if_sn.c:179i = inw(0x00)β DMA ch0 address register; - if_sn.c:182-189 (whensc->pccard_enaddr)outw(0x04, w),outw(0x06, w),outw(0x08, w)β writes the MAC address into the DMA ch1/ch2 address registers; - any latersninit()(if_sn.c:268outw(BASE+CONFIG_REG_W, flags)=outw(0x00, flags), if_sn.c:248outw(BASE+RECV_CONTROL_REG_W, RCR_SOFTRESET), etc.) scribbles further over the DMA controller / PIC-adjacent low ports. - The deterministic crash: if_sn.c:216
ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->irq_res));withsc->irq_res == NULL.rman_get_cpuid(r)expands to((r)->r_rm->rm_cpuid)(sys/sys/rman.h:157) β an immediate NULL-pointer dereference in kernel mode duringDEVICE_ATTACH, before the error path at if_sn.c:221-224 could ever run.
Why it is a real (if narrow) finding
- It is an error-path asymmetry of exactly the kind pass 2 hunts: the probe path checks the same call, the attach path does not.
- Impact ceiling on real hardware: kernel panic at boot/card-insertion time (availability), plus undefined low-port I/O side effects on the ISA DMA controller (system instability). Reachability requires a resource-allocation failure at attach (CIS resource conflict / IRQ steal in the probeβattach window) β plausible on pccard, rare otherwise.
- Not remotely triggerable, not an info leak, not memory corruption. Severity Low.
Why untested on this guest
if_sn.cis compiled only as theoptional snmodule (sys/conf/files:1247); its only front-end is pccard (sys/dev/netif/sn/if_sn_pccard.c:126-133,DEVMETHOD(device_attach, sn_pccard_attach)βsn_attach).- The QEMU guest (see
env.txt) exposes onlyvtnet0/lo0, has no PCMCIA slot and no SMC 91xx chip; therefore the attach path cannot execute. No amount of guest setup short of emulating PCMCIA + an SMC91C9x card can reach the bug β this is a genuine hardware gate, not a missing-setup case.
Fix validation
fix_status: not_testable for the same hardware reason. The one-line fix (check the return of sn_activate() in sn_attach and propagate the error) is contained in fix.diff; by inspection it makes the attach path return before any BASE-relative I/O and before the rman_get_cpuid call, mirroring the probe path at if_sn.c:1236-1237.
Kernel references
- sys/dev/netif/sn/if_sn.c:164 (unchecked return)
- sys/dev/netif/sn/if_sn.c:173-188 (BASE=0 port I/O: 0x0E/0x0A/0x00/0x04-0x08 β ISA DMA controller range)
- sys/dev/netif/sn/if_sn.c:216 (rman_get_cpuid(NULL))
- sys/dev/netif/sn/if_sn.c:1170-1192 (failure modes of sn_activate)
- sys/sys/rman.h:157 (rman_get_cpuid double-deref expansion)
- sys/dev/netif/sn/if_snreg.h:400 (BASE == sc->sn_io_addr)
- sys/dev/netif/sn/if_sn.c:1236-1237 (probe path does check β the asymmetry)
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_testablenot_testable: fix validation requires SMC91xx PCMCIA hardware (guest has none). The proposed fix.diff makes sn_attach() bail out immediately on sn_activate() failure, mirroring sn_probe() at if_sn.c:1236-1237; by inspection this removes both the rman_get_cpuid(NULL) deref and all BASE=0 port I/O on the failing path.
findings/poc/DF-4354/fix.diff (1-hunk, error propagation); env.txt (hardware absent).
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (root-cause chain with path:line), README.md (site table + fix), env.txt (guest lacks hardware: ifconfig -l shows vtnet0 lo0, no sn module loaded), fix.diff (one-line error propagation mirroring the probe path). Decisive lines: if_sn.c:164 (unchecked return), if_sn.c:216 (rman_get_cpuid(NULL)), sys/sys/rman.h:157 (((r)->r_rm->rm_cpuid)).
PoC changes
No executable PoC exists: path requires SMC91xx PCMCIA hardware absent from the guest. Evidence pack is source-level (VERDICT.md) plus guest hardware-inventory proof (env.txt).
Verified recommended fix
Check the return value of sn_activate() in sn_attach() and propagate the error before any register access or rman_get_cpuid call.
Verdict
sn_attach() (sys/dev/netif/sn/if_sn.c:164) discards the return value of sn_activate(); on any attach-time resource-allocation failure the driver proceeds with port_res=NULL, irq_res=NULL and BASE=0, writing the chip-id/MAC/CONFIG register writes into ISA DMA-controller ports 0x00-0x0F and then hitting ifq_set_cpuid(..., rman_get_cpuid(sc->irq_res)) at if_sn.c:216, a NULL double-deref (sys/sys/rman.h:157) that panics the kernel during device attach. Source-level certainty is high (the probe path checks the identical call at if_sn.c:1236-1237; the attach path does not), but the bug is hardware-gated: it requires an SMC91xx PCMCIA NIC, which the QEMU audit guest does not have (only vtnet0/lo0; if_sn is an optional module with a pccard-only front-end), so no runtime PoC is possible -> untested. Expected impact on real hardware is a boot/card-insert-time kernel panic plus stray low-port I/O; severity Low.
No comments yet.