ALSA: pcm: use lock to protect substream runtime resource

Use a spinlock to protect runtime resource in substream
against race conditions which may lead to use-after-free

CRs-fixed: 2112713
Change-Id: I37dee68cad5eae05b21cfade3dabc0c2b79be6b8
Signed-off-by: Karthikeyan Mani <kmani@codeaurora.org>
This commit is contained in:
Karthikeyan Mani 2017-09-28 11:06:55 -07:00 committed by Gerrit - the friendly Code Review server
parent de13ed16e8
commit 2c41ba8f59
2 changed files with 12 additions and 1 deletions

View File

@ -696,6 +696,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
}
substream->group = &substream->self_group;
spin_lock_init(&substream->self_group.lock);
spin_lock_init(&substream->runtime_lock);
INIT_LIST_HEAD(&substream->self_group.substreams);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
atomic_set(&substream->mmap_count, 0);
@ -992,9 +993,11 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
unsigned long flags = 0;
if (PCM_RUNTIME_CHECK(substream))
return;
spin_lock_irqsave(&substream->runtime_lock, flags);
runtime = substream->runtime;
if (runtime->private_free != NULL)
runtime->private_free(runtime);
@ -1011,6 +1014,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
put_pid(substream->pid);
substream->pid = NULL;
substream->pstr->substream_opened--;
spin_unlock_irqrestore(&substream->runtime_lock, flags);
}
static ssize_t show_pcm_class(struct device *dev,

View File

@ -63,9 +63,16 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
unsigned long ret = 0, flags = 0;
substream = timer->private_data;
return substream->runtime ? substream->runtime->timer_resolution : 0;
spin_lock_irqsave(&substream->runtime_lock, flags);
if (substream->runtime)
ret = substream->runtime->timer_resolution;
else
ret = 0;
spin_unlock_irqrestore(&substream->runtime_lock, flags);
return ret;
}
static int snd_pcm_timer_start(struct snd_timer * timer)