# 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`:

```c
} 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 assignment
- `sys/bus/u4b/input/wsp.c:894-921` — loop body assigns `sc->index[i] = f`
- `sys/bus/u4b/input/wsp.c:966` — NULL deref of `sc->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.
