diff options
author | Takashi Iwai <tiwai@suse.de> | 2022-06-17 16:40:49 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2022-06-20 09:36:02 +0200 |
commit | 94b98194b62e3fe3f27129d8e4b1f3fd7c5e972b (patch) | |
tree | 1220408576b9f1e25bf1db000de5800b74adb486 /sound/core/rawmidi.c | |
parent | f1d40433352e5d4babd59c0dd50b5f9414073ddb (diff) | |
download | lwn-94b98194b62e3fe3f27129d8e4b1f3fd7c5e972b.tar.gz lwn-94b98194b62e3fe3f27129d8e4b1f3fd7c5e972b.zip |
ALSA: rawmidi: Take open_mutex around parameter changes
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.
Link: https://lore.kernel.org/r/20220617144051.18985-4-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/rawmidi.c')
-rw-r--r-- | sound/core/rawmidi.c | 39 |
1 files changed, 25 insertions, 14 deletions
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); |