diff mbox series

[3/5] ALSA: rawmidi: Take open_mutex around parameter changes

Message ID 20220617144051.18985-4-tiwai@suse.de
State Accepted
Commit 94b98194b62e3fe3f27129d8e4b1f3fd7c5e972b
Headers show
Series ALSA: rawmidi: Make code robust for external calls | expand

Commit Message

Takashi Iwai June 17, 2022, 2:40 p.m. UTC
The input/output parameter changes are pretty intrusive, possibly
involving with the buffer resizing operation.  Hence those should be
performed exclusively; otherwise some ugly race could happen.

This patch puts the existing open_mutex for snd_rawmidi_input_params()
and *_output_params() for protecting the concurrent calls.  Since
those are exported, it's also meant for hardening from the external
calls, too.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/rawmidi.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 0a00f37d8c42..7fd6b369d46f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -712,11 +712,19 @@  static int resize_runtime_buffer(struct snd_rawmidi_substream *substream,
 int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
 			      struct snd_rawmidi_params *params)
 {
-	if (substream->append && substream->use_count > 1)
-		return -EBUSY;
+	int err;
+
 	snd_rawmidi_drain_output(substream);
-	substream->active_sensing = !params->no_active_sensing;
-	return resize_runtime_buffer(substream, params, false);
+	mutex_lock(&substream->rmidi->open_mutex);
+	if (substream->append && substream->use_count > 1)
+		err = -EBUSY;
+	else
+		err = resize_runtime_buffer(substream, params, false);
+
+	if (!err)
+		substream->active_sensing = !params->no_active_sensing;
+	mutex_unlock(&substream->rmidi->open_mutex);
+	return err;
 }
 EXPORT_SYMBOL(snd_rawmidi_output_params);
 
@@ -727,19 +735,22 @@  int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
 	unsigned int clock_type = params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK;
 	int err;
 
+	snd_rawmidi_drain_input(substream);
+	mutex_lock(&substream->rmidi->open_mutex);
 	if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE)
-		return -EINVAL;
+		err = -EINVAL;
 	else if (clock_type > SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW)
-		return -EINVAL;
-	if (framing > SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
-		return -EINVAL;
-	snd_rawmidi_drain_input(substream);
-	err = resize_runtime_buffer(substream, params, true);
-	if (err < 0)
-		return err;
+		err = -EINVAL;
+	else if (framing > SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
+		err = -EINVAL;
+	else
+		err = resize_runtime_buffer(substream, params, true);
 
-	substream->framing = framing;
-	substream->clock_type = clock_type;
+	if (!err) {
+		substream->framing = framing;
+		substream->clock_type = clock_type;
+	}
+	mutex_unlock(&substream->rmidi->open_mutex);
 	return 0;
 }
 EXPORT_SYMBOL(snd_rawmidi_input_params);