Revert "ALSA: pcm: Fix races among concurrent hw_params and hw_free calls"
This reverts commit 33061d0fba.
It will come back after the next ABI break as it is needed to resolve
CVE-2022-1048. But for now, while testing, it can be reverted in order
to preserve the ABI.
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Iebd89734d6d1b0bdb3aaa9e8b52fc07345377a64
This commit is contained in:
@@ -398,7 +398,6 @@ struct snd_pcm_runtime {
|
|||||||
wait_queue_head_t tsleep; /* transfer sleep */
|
wait_queue_head_t tsleep; /* transfer sleep */
|
||||||
struct fasync_struct *fasync;
|
struct fasync_struct *fasync;
|
||||||
bool stop_operating; /* sync_stop will be called */
|
bool stop_operating; /* sync_stop will be called */
|
||||||
struct mutex buffer_mutex; /* protect for buffer changes */
|
|
||||||
|
|
||||||
/* -- private section -- */
|
/* -- private section -- */
|
||||||
void *private_data;
|
void *private_data;
|
||||||
|
|||||||
@@ -969,7 +969,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
|||||||
init_waitqueue_head(&runtime->tsleep);
|
init_waitqueue_head(&runtime->tsleep);
|
||||||
|
|
||||||
runtime->status->state = SNDRV_PCM_STATE_OPEN;
|
runtime->status->state = SNDRV_PCM_STATE_OPEN;
|
||||||
mutex_init(&runtime->buffer_mutex);
|
|
||||||
|
|
||||||
substream->runtime = runtime;
|
substream->runtime = runtime;
|
||||||
substream->private_data = pcm->private_data;
|
substream->private_data = pcm->private_data;
|
||||||
@@ -1003,7 +1002,6 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
|
|||||||
} else {
|
} else {
|
||||||
substream->runtime = NULL;
|
substream->runtime = NULL;
|
||||||
}
|
}
|
||||||
mutex_destroy(&runtime->buffer_mutex);
|
|
||||||
kfree(runtime);
|
kfree(runtime);
|
||||||
put_pid(substream->pid);
|
put_pid(substream->pid);
|
||||||
substream->pid = NULL;
|
substream->pid = NULL;
|
||||||
|
|||||||
@@ -672,40 +672,33 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
|
|
||||||
#define is_oss_stream(substream) ((substream)->oss.oss)
|
|
||||||
#else
|
|
||||||
#define is_oss_stream(substream) false
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
int err = 0, usecs;
|
int err, usecs;
|
||||||
unsigned int bits;
|
unsigned int bits;
|
||||||
snd_pcm_uframes_t frames;
|
snd_pcm_uframes_t frames;
|
||||||
|
|
||||||
if (PCM_RUNTIME_CHECK(substream))
|
if (PCM_RUNTIME_CHECK(substream))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
mutex_lock(&runtime->buffer_mutex);
|
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
switch (runtime->status->state) {
|
switch (runtime->status->state) {
|
||||||
case SNDRV_PCM_STATE_OPEN:
|
case SNDRV_PCM_STATE_OPEN:
|
||||||
case SNDRV_PCM_STATE_SETUP:
|
case SNDRV_PCM_STATE_SETUP:
|
||||||
case SNDRV_PCM_STATE_PREPARED:
|
case SNDRV_PCM_STATE_PREPARED:
|
||||||
if (!is_oss_stream(substream) &&
|
|
||||||
atomic_read(&substream->mmap_count))
|
|
||||||
err = -EBADFD;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err = -EBADFD;
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
break;
|
return -EBADFD;
|
||||||
}
|
}
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
if (err)
|
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
|
||||||
goto unlock;
|
if (!substream->oss.oss)
|
||||||
|
#endif
|
||||||
|
if (atomic_read(&substream->mmap_count))
|
||||||
|
return -EBADFD;
|
||||||
|
|
||||||
snd_pcm_sync_stop(substream, true);
|
snd_pcm_sync_stop(substream, true);
|
||||||
|
|
||||||
@@ -793,21 +786,16 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||||||
if (usecs >= 0)
|
if (usecs >= 0)
|
||||||
cpu_latency_qos_add_request(&substream->latency_pm_qos_req,
|
cpu_latency_qos_add_request(&substream->latency_pm_qos_req,
|
||||||
usecs);
|
usecs);
|
||||||
err = 0;
|
return 0;
|
||||||
_error:
|
_error:
|
||||||
if (err) {
|
/* hardware might be unusable from this time,
|
||||||
/* hardware might be unusable from this time,
|
so we force application to retry to set
|
||||||
* so we force application to retry to set
|
the correct hardware parameter settings */
|
||||||
* the correct hardware parameter settings
|
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
||||||
*/
|
if (substream->ops->hw_free != NULL)
|
||||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
substream->ops->hw_free(substream);
|
||||||
if (substream->ops->hw_free != NULL)
|
if (substream->managed_buffer_alloc)
|
||||||
substream->ops->hw_free(substream);
|
snd_pcm_lib_free_pages(substream);
|
||||||
if (substream->managed_buffer_alloc)
|
|
||||||
snd_pcm_lib_free_pages(substream);
|
|
||||||
}
|
|
||||||
unlock:
|
|
||||||
mutex_unlock(&runtime->buffer_mutex);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,31 +835,26 @@ static int do_hw_free(struct snd_pcm_substream *substream)
|
|||||||
static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
|
static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
int result = 0;
|
int result;
|
||||||
|
|
||||||
if (PCM_RUNTIME_CHECK(substream))
|
if (PCM_RUNTIME_CHECK(substream))
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
mutex_lock(&runtime->buffer_mutex);
|
|
||||||
snd_pcm_stream_lock_irq(substream);
|
snd_pcm_stream_lock_irq(substream);
|
||||||
switch (runtime->status->state) {
|
switch (runtime->status->state) {
|
||||||
case SNDRV_PCM_STATE_SETUP:
|
case SNDRV_PCM_STATE_SETUP:
|
||||||
case SNDRV_PCM_STATE_PREPARED:
|
case SNDRV_PCM_STATE_PREPARED:
|
||||||
if (atomic_read(&substream->mmap_count))
|
|
||||||
result = -EBADFD;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = -EBADFD;
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
break;
|
return -EBADFD;
|
||||||
}
|
}
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
snd_pcm_stream_unlock_irq(substream);
|
||||||
if (result)
|
if (atomic_read(&substream->mmap_count))
|
||||||
goto unlock;
|
return -EBADFD;
|
||||||
result = do_hw_free(substream);
|
result = do_hw_free(substream);
|
||||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
||||||
cpu_latency_qos_remove_request(&substream->latency_pm_qos_req);
|
cpu_latency_qos_remove_request(&substream->latency_pm_qos_req);
|
||||||
unlock:
|
|
||||||
mutex_unlock(&runtime->buffer_mutex);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user