summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2022-03-22 18:07:20 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-03-28 09:57:09 +0200
commitb560d670c87d7d40b3cf6949246fa4c7aa65a00a (patch)
treede10d93f5461c25ab3e8e7a21c111c07311929e1 /sound
parenta38440f006974e693f92a1ea10f819eccc4dcc37 (diff)
ALSA: pcm: Fix races among concurrent prealloc proc writes
commit 69534c48ba8ce552ce383b3dfdb271ffe51820c3 upstream. We have no protection against concurrent PCM buffer preallocation changes via proc files, and it may potentially lead to UAF or some weird problem. This patch applies the PCM open_mutex to the proc write operation for avoiding the racy proc writes and the PCM stream open (and further operations). Cc: <stable@vger.kernel.org> Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20220322170720.3529-5-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_memory.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 4f03ba8ed0ae..a9a0d74f3165 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -164,19 +164,20 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
size_t size;
struct snd_dma_buffer new_dmab;
+ mutex_lock(&substream->pcm->open_mutex);
if (substream->runtime) {
buffer->error = -EBUSY;
- return;
+ goto unlock;
}
if (!snd_info_get_line(buffer, line, sizeof(line))) {
snd_info_get_str(str, line, sizeof(str));
size = simple_strtoul(str, NULL, 10) * 1024;
if ((size != 0 && size < 8192) || size > substream->dma_max) {
buffer->error = -EINVAL;
- return;
+ goto unlock;
}
if (substream->dma_buffer.bytes == size)
- return;
+ goto unlock;
memset(&new_dmab, 0, sizeof(new_dmab));
new_dmab.dev = substream->dma_buffer.dev;
if (size > 0) {
@@ -185,7 +186,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
substream->dma_buffer.dev.dev,
size, &new_dmab) < 0) {
buffer->error = -ENOMEM;
- return;
+ goto unlock;
}
substream->buffer_bytes_max = size;
} else {
@@ -197,6 +198,8 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
} else {
buffer->error = -EINVAL;
}
+ unlock:
+ mutex_unlock(&substream->pcm->open_mutex);
}
static inline void preallocate_info_init(struct snd_pcm_substream *substream)