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

NULL-deref in wsp_intr_callback when first HID report yields ntouch=0 (always for TYPE1 devices)

Summary

wsp_intr_callback unconditionally dereferences sc->index[0]->touch_major at :966 (and index[1]/index[2] later) but sc->index[] only populated inside finger loop at :920 gated on ntouch>0. Softc zero-allocated M_ZERO so sc->index[0] is NULL until first report with ntouch>=1. For TYPE1 devices driver never reads ntouch (byte read guarded by params->tp_type>=TYPE2 at :884) so ntouch stays 0 and panic automatic on every report. For TYPE2+ malicious device sends valid-length report with ntouch byte cleared first report panics. sc->index[0]->touch_major reads address offsetof(tp_finger touch_major)=16 unmapped low address. Callback in USB interrupt thread context holding sc->sc_lock. Reliable local kernel panic DoS from USB device enumerating as Apple trackpad. wsp in GENERIC auto-attaches to all listed PIDs.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2338 Β· 6 files
FileTypeDescriptionSize
VERDICT.md verdict gate analysis + ntouch==0 NULL-deref trace 3.4 KB ↓ raw
fix.diff suggested-fix early-skip index-deref logic when ntouch==0 834 B view raw
build.sh build-script documents HW gate 155 B view raw
run.sh run-script prints gate proof 265 B view raw
env.txt environment guest env 1.1 KB view raw
usb_gate.txt gate-proof usbconfig empty, no /dev/ugen*/wsp* 375 B view raw
VERDICT.md verdict gate analysis + ntouch==0 NULL-deref trace
↓ download raw

DF-2338 β€” NULL-deref in wsp_intr_callback when ntouch==0 (sys/bus/u4b/input/wsp.c)

Verdict: NOT REPRODUCED (HW-gated); REAL BUG IN SOURCE (defense-in-depth fix warranted)

Hardware gate (why the PoC cannot run on this guest)

wsp is the Apple Wireless Trackpad / Magic Trackpad USB HID driver. It attaches only to specific Apple USB trackpad products (VID 0x05ac PIDs 0x0221/0x0230/ 0x0236/0x0307 etc. β€” see wsp_devs[]). The audit QEMU/KVM guest has no USB device of any kind attached, let alone an Apple trackpad:

$ usbconfig list               # No device match or lack of permissions.
$ ls /dev/ugen* /dev/wsp*      # No such file or directory
$ ls /dev/usb*                 # only /dev/usbctl (operator group; maxx not in operator)
$ id maxx                      # uid=1001(maxx) gid=1001(maxx) groups=1001(maxx)

With no matching USB device the wsp driver never probes/attaches, so its USB interrupt callback wsp_intr_callback never executes. The unprivileged maxx user cannot plug a USB trackpad into the QEMU guest nor inject a HID report.

Source trace β€” the bug is REAL (sys/bus/u4b/input/wsp.c)

Softc field (wsp.c:550): struct tp_finger *index[MAX_FINGERS]; β€” an array of pointers, zero-initialised (softc allocated with M_ZERO).

The interrupt callback (wsp.c:882-966) computes ntouch:

h = (struct tp_header *)(sc->tp_data);
if (params->tp_type >= TYPE2) {                  /* wsp.c:884 */
    ibt    = sc->tp_data[params->tp_button];
    ntouch = sc->tp_data[params->tp_button - 1]; /* only read for TYPE2+ */
}
if (ntouch < 0)              ntouch = 0;         /* wsp.c:889 */
else if (ntouch > MAX_FINGERS) ntouch = MAX_FINGERS;

for (i = 0; i != ntouch; i++) {                  /* wsp.c:894 */
    f = (struct tp_finger *)(sc->tp_data + params->tp_offset + ...);
    ...
    sc->index[i] = f;                            /* wsp.c:920 β€” ONLY assignment */
}

For TYPE1 devices the ntouch byte is never read (the read is gated on params->tp_type >= TYPE2 at line 884), so ntouch stays 0, the loop body never runs, and sc->index[0..] remain NULL. Then at line 966 (and 942/947/952/1027/ 1030/1040) the code unconditionally dereferences sc->index[0]->touch_major:

if (sc->index[0]->touch_major < tun.pressure_untouch_threshold &&  /* wsp.c:966 */
    sc->sc_status.button == 0) {

β†’ NULL dereference: reads address offsetof(struct tp_finger, touch_major) β‰ˆ 16, an unmapped low address β†’ kernel panic in the USB interrupt thread context holding sc->sc_lock. For TYPE2+ devices a malicious unit sending a valid-length report with the ntouch byte cleared panics on the first report.

Trigger: a USB device enumerating as an Apple trackpad (automatic attach via wsp_devs[] PIDs which are in the GENERIC kernel). No privilege, no user interaction beyond plug-in. Reliable local kernel panic / DoS.

Exploit chain status

Not pursuable β€” primitive (NULL-deref panic) behind absent USB trackpad hardware (valid Phase-6 hard blocker: dead path at runtime on this guest). The primitive is a pure DoS panic, not a write primitive; no escalation chain.

PoC changes

None. No USB trackpad on guest; verified by source trace only.

Guard the sc->index[0] dereferences against ntouch == 0 (skip the tap/untouch logic when no fingers are present). See fix.diff (matches finding proposal: add an ntouch == 0 early-skip / NULL guard before the index dereferences).

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_testable: PoC cannot run on this guest (HW-gated, no target device). fix.diff validated by git apply --check (clean) + line-accurate source trace confirming it closes the cited path.

git apply --check findings/poc/DF-2338/fix.diff -> OK (clean apply). No runtime test possible (HW-gated).
↓ fix.diffn/a (no target HW/device on this guest)

Confirmed kernel references

Detail

Exploit chain

none β€” valid hard blocker (driver/device path dead at runtime on this guest: no target HW / no attached device). No unprivileged->root path.

Evidence (decisive lines)

usbconfig list -> No device match or lack of permissions.; pciconf -l -> no target controller HW; ifconfig -l -> vtnet0 lo0; kldstat -> kernel/ehci/xhci only; ls /dev/<target> -> No such file or directory; id maxx -> uid=1001 groups=1001 (not operator). Source confirmed at cited lines.

PoC changes

Created findings/poc/DF-2338/{VERDICT.md,fix.diff,build.sh,run.sh,env.txt,gate_proof.txt,manifest.json}. No PoC source (HW-gated).

Verified recommended fix

early-skip index-deref block when ntouch==0. Full git-apply-able diff in findings/poc/DF-2338/fix.diff (git apply --check OK).

Verdict

NOT REPRODUCED (HW-gated). The bug is REAL in source (traced line-by-line). wsp_intr_callback NULL-deref when first HID report has ntouch==0; no Apple USB trackpad. Gate confirmed via usbconfig list (No device match / no /dev/ugen*), pciconf -l (no target controller HW), ifconfig (vtnet0 lo0 only), kldstat (no target module), and ls /dev (no target nodes). maxx (uid 1001, not in operator) cannot reach any /dev/usbctl write path.