From afb74299dd59eace12ccd7f1e79fdf6c6c867076 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 22 Mar 2011 17:14:47 +0100 Subject: [PATCH] ALSA: isight: fix isight_pcm_abort() crashes Fix crashes in isight_pcm_abort() that happen when the driver tries to access isight->pcm->runtime which does not exist when the device is not open. Introduce a new field pcm_active to track this state. Signed-off-by: Clemens Ladisch Reported-by: Stefan Richter --- sound/firewire/isight.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 0d5fa49fb87..4043d9bdc70 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -55,6 +55,7 @@ struct isight { struct iso_packets_buffer buffer; struct fw_iso_resources resources; struct fw_iso_context *context; + bool pcm_active; bool pcm_running; bool first_packet; int packet_index; @@ -130,10 +131,12 @@ static void isight_pcm_abort(struct isight *isight) { unsigned long flags; - snd_pcm_stream_lock_irqsave(isight->pcm, flags); - if (snd_pcm_running(isight->pcm)) - snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); + if (ACCESS_ONCE(isight->pcm_active)) { + snd_pcm_stream_lock_irqsave(isight->pcm, flags); + if (snd_pcm_running(isight->pcm)) + snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); + } } static void isight_dropped_samples(struct isight *isight, unsigned int total) @@ -294,8 +297,17 @@ static int isight_close(struct snd_pcm_substream *substream) static int isight_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + struct isight *isight = substream->private_data; + int err; + + err = snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + if (err < 0) + return err; + + ACCESS_ONCE(isight->pcm_active) = true; + + return 0; } static void isight_stop_streaming(struct isight *isight) @@ -321,6 +333,8 @@ static int isight_hw_free(struct snd_pcm_substream *substream) { struct isight *isight = substream->private_data; + ACCESS_ONCE(isight->pcm_active) = false; + mutex_lock(&isight->mutex); isight_stop_streaming(isight); mutex_unlock(&isight->mutex); -- 2.11.4.GIT