From 8f22e52528cc372b218b5f100457469615c733ce Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 26 Apr 2018 09:17:45 +0200 Subject: ALSA: seq: Fix races at MIDI encoding in snd_virmidi_output_trigger() 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 Cc: Signed-off-by: Takashi Iwai --- sound/core/seq/seq_virmidi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/core') diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index f48a4cd24ffc..289ae6bb81d9 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -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) -- cgit From f13876e2c33a657a71bcbb10f767c0951b165020 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 May 2018 08:48:46 +0200 Subject: ALSA: pcm: Check PCM state at xfern compat ioctl Since snd_pcm_ioctl_xfern_compat() has no PCM state check, it may go further and hit the sanity check pcm_sanity_check() when the ioctl is called right after open. It may eventually spew a kernel warning, as triggered by syzbot, depending on kconfig. The lack of PCM state check there was just an oversight. Although it's no real crash, the spurious kernel warning is annoying, so let's add the proper check. Reported-by: syzbot+1dac3a4f6bc9c1c675d4@syzkaller.appspotmail.com Cc: Signed-off-by: Takashi Iwai --- sound/core/pcm_compat.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/core') diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 06d7c40af570..6491afbb5fd5 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -423,6 +423,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; if ((ch = substream->runtime->channels) > 128) return -EINVAL; -- cgit From 3f12888dfae2a48741c4caa9214885b3aaf350f9 Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Sat, 5 May 2018 13:38:03 -0500 Subject: ALSA: control: fix a redundant-copy issue In snd_ctl_elem_add_compat(), the fields of the struct 'data' need to be copied from the corresponding fields of the struct 'data32' in userspace. This is achieved by invoking copy_from_user() and get_user() functions. The problem here is that the 'type' field is copied twice. One is by copy_from_user() and one is by get_user(). Given that the 'type' field is not used between the two copies, the second copy is *completely* redundant and should be removed for better performance and cleanup. Also, these two copies can cause inconsistent data: as the struct 'data32' resides in userspace and a malicious userspace process can race to change the 'type' field between the two copies to cause inconsistent data. Depending on how the data is used in the future, such an inconsistency may cause potential security risks. For above reasons, we should take out the second copy. Signed-off-by: Wenwen Wang Cc: Signed-off-by: Takashi Iwai --- sound/core/control_compat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/core') diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index a848836a5de0..507fd5210c1c 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -396,8 +396,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) goto error; - if (get_user(data->owner, &data32->owner) || - get_user(data->type, &data32->type)) + if (get_user(data->owner, &data32->owner)) goto error; switch (data->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: -- cgit