Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1e4b1ca authored by Takashi Iwai's avatar Takashi Iwai Committed by Greg Kroah-Hartman
Browse files

ALSA: virmidi: Fix too long output trigger loop



commit 50e9ffb1996a5d11ff5040a266585bad4ceeca0a upstream.

The virmidi output trigger tries to parse the all available bytes and
process sequencer events as much as possible.  In a normal situation,
this is supposed to be relatively short, but a program may give a huge
buffer and it'll take a long time in a single spin lock, which may
eventually lead to a soft lockup.

This patch simply adds a workaround, a cond_resched() call in the loop
if applicable.  A better solution would be to move the event processor
into a work, but let's put a duct-tape quickly at first.

Reported-and-tested-by: default avatarDae R. Jeong <threeearcat@gmail.com>
Reported-by: default avatar <syzbot+619d9f40141d826b097e@syzkaller.appspotmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5cb12033
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
	int count, res;
	unsigned char buf[32], *pbuf;
	unsigned long flags;
	bool check_resched = !in_atomic();

	if (up) {
		vmidi->trigger = 1;
@@ -200,6 +201,15 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
					vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
				}
			}
			if (!check_resched)
				continue;
			/* do temporary unlock & cond_resched() for avoiding
			 * CPU soft lockup, which may happen via a write from
			 * a huge rawmidi buffer
			 */
			spin_unlock_irqrestore(&substream->runtime->lock, flags);
			cond_resched();
			spin_lock_irqsave(&substream->runtime->lock, flags);
		}
	out:
		spin_unlock_irqrestore(&substream->runtime->lock, flags);