β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1038

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1038 Β· 8 files
FileTypeDescriptionSize
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
README.md readme human-readable summary
↓ download 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.

VERDICT.md verdict detailed analysis
↓ download raw

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):

  • :845 int ntouch = 0; β€” initialized to 0.
  • :884-887 only if (params->tp_type >= TYPE2) reads ntouch from the device payload; TYPE1 (WELLSPRING1/2) has no else branch, so ntouch stays 0 on every TYPE1 report.
  • :894-921 for (i = 0; i != ntouch; i++) runs zero times on TYPE1; sc->index[0] is never assigned and remains NULL (the softc is allocated with M_ZERO).
  • :966 if (sc->index[0]->touch_major < ...) { unconditionally dereferences sc->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

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_testable

compile+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.