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

mpu401_un_init frees mpu401 struct without stopping/draining the live callout (use-after-free via mpu401_timeout)

Summary

mpu401_init arms recursive callout on m->timer (callout_init_mp line 179) re-armed every tick during TX by mpu401_intr (162-164) and mpu401_mcallback (265-267). mpu401_un_init (197-207): CMD RESET -> midi_uninit(m->mid) -> kfree(m,M_MIDI) WITHOUT callout_stop/drain. Pending mpu401_timeout (103-111) dereferences freed m via m->si (function pointer) and m->cookie -> UAF read of fn ptr + indirect call (m->si)(m->cookie) if slab reused. Attacker: unprivileged local user opens /dev/midi* (mode 0666 midi.c:364) writes MIDI data -> M_TXEN set -> callout armed 1 tick repeat. Admin detaches sound device (kldunload snd_*) -> mpu401_un_init -> kfree(m) -> callout fires -> UAF. Best case NULL deref panic DoS; worst case slab grooming m->si fn ptr control -> kernel arbitrary code exec. midi_uninit/midi_destroy frees snd_midi does NOT touch m->timer (midi.c:418-438). AV:L/AC:H/PR:L/UI:R(detach), C:H/I:H/A:H. Fix: callout_cancel before CMD RESET + callout_cancel+callout_drain after midi_uninit before kfree.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2084 Β· 2 files
FileTypeDescriptionSize
fix.diff suggested-fix git-apply-able fix 245 B view raw
VERDICT.md verdict source-trace confirmation 677 B ↓ raw
VERDICT.md verdict source-trace confirmation
↓ download raw

DF-2084 β€” mpu401_un_init UAF: callout not drained before kfree

Verdict

REPRODUCED (source-only confirmation). Bug confirmed by source tracing.

Mechanism

mpu401_init (mpu401.c:179) initializes callout m->timer. mpu401_intr (162-164) and mpu401_mcallback (265-267) re-arm it every tick during TX. mpu401_un_init (197-207) does CMD RESET + midi_uninit + kfree(m) but never calls callout_stop/callout_drain. If the callout is pending, it fires after free -> UAF.

Fix

Add callout_stop(&m->timer) + callout_drain(&m->timer) before kfree in mpu401_un_init.

Batch-build status

Applied with all 24 other fixes; kernel + modules compiled rc=0, 0 errors, -Werror.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

Added callout_stop+drain; batch build rc=0.

Added callout_stop+drain; batch build rc=0.
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

mpu401_un_init kfrees m without callout_stop -> UAF.

Verified recommended fix

mpu401_un_init kfrees m without callout_stop -> UAF.

Verdict

mpu401_un_init kfrees m without callout_stop -> UAF.