Skip to content

Commit

Permalink
ALSA: seq: Fix races at MIDI encoding in snd_virmidi_output_trigger()
Browse files Browse the repository at this point in the history
The sequencer virmidi code has an open race at its output trigger
callback: namely, virmidi keeps only one event packet for processing
while it doesn't protect for concurrent output trigger calls.

snd_virmidi_output_trigger() tries to process the previously
unfinished event before starting encoding the given MIDI stream, but
this is done without any lock.  Meanwhile, if another rawmidi stream
starts the output trigger, this proceeds further, and overwrites the
event package that is being processed in another thread.  This
eventually corrupts and may lead to the invalid memory access if the
event type is like SYSEX.

The fix is just to move the spinlock to cover both the pending event
and the new stream.

The bug was spotted by a new fuzzer, RaceFuzzer.

BugLink: http://lkml.kernel.org/r/[email protected]
Reported-by: DaeRyong Jeong <[email protected]>
Cc: <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Apr 27, 2018
1 parent 6a30aba commit 8f22e52
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions sound/core/seq/seq_virmidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
}
return;
}
spin_lock_irqsave(&substream->runtime->lock, flags);
if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
return;
goto out;
vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
}
spin_lock_irqsave(&substream->runtime->lock, flags);
while (1) {
count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
if (count <= 0)
Expand Down

0 comments on commit 8f22e52

Please sign in to comment.