[BUG] ALSA: ump: NULL deref of legacy_rmidi after parse sets parsed
From: Qingyu Zhang
Date: Tue Sep 01 2026 - 22:07:56 EST
Hello,
ump_legacy_set_rawmidi_name() snprintf()s into ump->legacy_rmidi->name
when ump->parsed is true, but parsed is set at the end of
snd_ump_parse_endpoint() *before* snd_ump_attach_legacy_rawmidi().
A UMP packet in that window NULL-derefs.
Type: null-pointer dereference
* Summary
snd_ump_parse_endpoint() always does:
error:
ump->parsed = true;
...
ump_handle_ep_name_msg():
if (ret && ump->parsed) {
ump_set_rawmidi_name(ump);
ump_legacy_set_rawmidi_name(ump); /* rmidi may be NULL */
}
ump_legacy_set_rawmidi_name():
rmidi = ump->legacy_rmidi;
snprintf(rmidi->name, ...); /* no NULL check */
This runs from snd_ump_receive() on the USB input URB complete path
(in interrupt).
* Affected
37e0e14128e0. Needs CONFIG_SND_UMP, CONFIG_SND_UMP_LEGACY_RAWMIDI,
CONFIG_SND_USB_AUDIO, a MIDI 2.0 gadget or device. KASAN.
The natural window is parse-done vs attach. The QEMU PoC widens it
with a kprobe on snd_ump_receive (poc/widen_ump.c) plus dummy_hcd
configfs midi2, because the un-widened window is short.
* Reproduction
# dummy_hcd + configfs usb_gadget midi2.usb0 (see poc/run.sh)
# with widen_ump.ko: force parsed=1, legacy_rmidi=NULL on receive
KASAN: null-ptr-deref in snprintf from ump_legacy_set_rawmidi_name
<- ump_handle_ep_name_msg <- snd_ump_receive <- input_urb_complete.
Then "Fatal exception in interrupt".
* Expected
legacy_rmidi helpers no-op until attach has stored the pointer.
* Actual
IRQ-context NULL deref.
Please consider the suggested patch
Thanks.
Suggested patch:
```
diff --git a/sound/core/ump.c b/sound/core/ump.c
index d183c8a000bd..3d1a2ed3b476 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -1335,6 +1335,8 @@ static void update_legacy_names(struct
snd_ump_endpoint *ump)
{
struct snd_rawmidi *rmidi = ump->legacy_rmidi;
+ if (!rmidi)
+ return;
update_legacy_substreams(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
update_legacy_substreams(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
}
@@ -1343,6 +1345,8 @@ static void ump_legacy_set_rawmidi_name(struct
snd_ump_endpoint *ump)
{
struct snd_rawmidi *rmidi = ump->legacy_rmidi;
+ if (!rmidi)
+ return;
snprintf(rmidi->name, sizeof(rmidi->name), "%.68s (MIDI 1.0)",
ump->core.name);
}
```