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>
This commit is contained in:
Takashi Iwai 2022-06-17 16:40:49 +02:00
parent f1d4043335
commit 94b98194b6
1 changed files with 26 additions and 15 deletions

View File

@ -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;
if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE)
return -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;
mutex_lock(&substream->rmidi->open_mutex);
if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE)
err = -EINVAL;
else if (clock_type > SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW)
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);