| From: Takashi Iwai <tiwai@suse.de> |
| Date: Thu, 26 Apr 2018 09:17:45 +0200 |
| Subject: ALSA: seq: Fix races at MIDI encoding in snd_virmidi_output_trigger() |
| |
| commit 8f22e52528cc372b218b5f100457469615c733ce upstream. |
| |
| 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/20180426045223.GA15307@dragonet.kaist.ac.kr |
| Reported-by: DaeRyong Jeong <threeearcat@gmail.com> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| sound/core/seq/seq_virmidi.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/sound/core/seq/seq_virmidi.c |
| +++ b/sound/core/seq/seq_virmidi.c |
| @@ -174,12 +174,12 @@ static void snd_virmidi_output_trigger(s |
| } |
| 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) |