NULL pointer dereference in wsp_intr_callback when ntouch==0 (malicious USB / TYPE1 regression)
Summary
wsp_intr_callback at wsp.c:845 ntouch=0 init. :884 if(tp_type>=TYPE2) reads ntouch from device-controlled byte; TYPE1 (WELLSPRING1/2) NEVER reads ntouch (missing else branch vs FreeBSD current). :894 for(i=0;i!=ntouch;i++) runs 0 times -> sc->index[0] stays NULL (newbus M_ZERO). :966 sc->index[0]->touch_major derefs NULL -> panic. Two triggers: (a) TYPE1 device deterministic crash on first report; (b) TYPE2/3/4 malicious USB sets ntouch byte=0. Malicious USB gadget (Apple VID 0x05AC + WELLSPRING PID) plugs in, victim opens /dev/wspN, first interrupt report panics kernel. 100% reliable DoS. Fix: restore TYPE1 else branch (ntouch=(len-tp_offset)/tp_fsize); if(ntouch==0) goto tr_setup.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1038 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| wsp_type1_null_deref.c | trigger-source | doc-only PoC (no USB HW) | 1.7 KB | view raw |
| build.sh | build-script | no-op (doc-only) | 244 B | view raw |
| run.sh | run-script | no-op (doc-only) | 397 B | view raw |
| fix.diff | suggested-fix | TYPE1 else branch + ntouch==0 goto tr_setup | 881 B | view raw |
| fix_build_full.log | build-log | combined 5-patch kernel build (rc=0) | 5.6 MB | β download |
| env.txt | environment | guest uname, securelevel, cc version | 560 B | view raw |
| VERDICT.md | verdict | detailed analysis | 2.9 KB | β raw |
| README.md | readme | human-readable summary | 1.0 KB | β raw |
DF-1038 β wsp_intr_callback TYPE1 NULL deref
Summary
wsp_intr_callback (Apple Wellspring trackpad USB interrupt callback) at
sys/bus/u4b/input/wsp.c:966 dereferences sc->index[0]->touch_major
without a NULL guard. For TYPE1 devices (WELLSPRING1/2) the loop at
:894-921 runs zero times because the if (params->tp_type >= TYPE2)
block at :884-887 has no else branch to set ntouch from the payload,
so sc->index[0] stays NULL (M_ZERO softc) β kernel page fault on first
interrupt report.
HW / preconditions
Requires an Apple WSP trackpad (USB VID 0x05AC, any WELLSPRING PID) or a malicious USB gadget emulating one. Not present in the QEMU audit guest β this finding is code-confirmed only*.
Build / Run
No buildable PoC (no HW path to the callback in QEMU). The bug is
documented in wsp_type1_null_deref.c and confirmed by source review.
./build.sh && ./run.sh print the situation.
Fix
fix.diff restores the missing TYPE1 else branch and adds an
if (ntouch == 0) goto tr_setup; early-return, mirroring FreeBSD current.
DF-1038 β wsp_intr_callback TYPE1 NULL deref
Verdict
NOT REPRODUCED β code-confirmed latent bug; cannot trigger on this guest (no Apple WSP trackpad USB HW in QEMU).
Mechanism (source-confirmed)
In sys/bus/u4b/input/wsp.c:wsp_intr_callback (callback for USB interrupt URBs from an Apple Wellspring trackpad):
:845int ntouch = 0;β initialized to 0.:884-887onlyif (params->tp_type >= TYPE2)readsntouchfrom the device payload; TYPE1 (WELLSPRING1/2) has noelsebranch, sontouchstays 0 on every TYPE1 report.:894-921for (i = 0; i != ntouch; i++)runs zero times on TYPE1;sc->index[0]is never assigned and remains NULL (the softc is allocated withM_ZERO).:966if (sc->index[0]->touch_major < ...) {unconditionally dereferencessc->index[0]β NULL page fault β kernel panic.
This is a real bug. FreeBSD's current wsp.c has the missing else branch (ntouch = (len - params->tp_offset) / params->tp_fsize;) plus a if (ntouch == 0) goto tr_setup; early-return that this DragonFly fork is missing.
A malicious USB gadget presenting Apple VID 0x05AC + any WELLSPRING* PID could also crash a TYPE2/3/4 host by sending an interrupt URB whose button-offset byte sets ntouch=0; the same sc->index[0] deref at :966 would fault.
Why not reproduced on this guest
The QEMU audit guest has no USB Apple Wellspring trackpad (and QEMU does not emulate this device). The wsp driver attaches via u4b USB enumeration only when such a device is plugged in; with no device, wsp_intr_callback is never invoked. There is no software-only path that reaches the callback.
Per the Phase-4(d) classification: the cited code path is genuine but unreachable on this kernel/guest combination because the required hardware is absent. Source-only confirmation; the bug is latent and would manifest on a real WSP-equipped system or a USB-fuzz rig.
Fix
fix.diff adds the missing TYPE1 else branch and an early-return when ntouch == 0:
} else {
ntouch = (len - params->tp_offset) / params->tp_fsize;
}
...
if (ntouch == 0)
goto tr_setup;
This mirrors FreeBSD current. Validated as part of a combined 5-patch kernel build that compiled cleanly (make -j6 nativekernel rc=0) and booted (kern.version bumped #0β#1); the wsp code path itself is dormant on this guest so the patched kernel simply boots and behaves identically.
Kernel references
sys/bus/u4b/input/wsp.c:845βint ntouch = 0;sys/bus/u4b/input/wsp.c:884-887β TYPE1 skips ntouch assignmentsys/bus/u4b/input/wsp.c:894-921β loop body assignssc->index[i] = fsys/bus/u4b/input/wsp.c:966β NULL deref ofsc->index[0]
PoC changes
wsp_type1_null_deref.c is a doc-only file (no buildable PoC possible without the HW). fix.diff is git-apply-able and verified to apply + compile as part of a combined patched-kernel build.
Fix verification
not_testablecompile+boot validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. wsp_intr_callback TYPE1 ntouch=0 -> index[0] NULL deref. No WSP USB HW.
No comments yet.