From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932106AbbJTJqw (ORCPT ); Tue, 20 Oct 2015 05:46:52 -0400 Received: from smtp-out-200.synserver.de ([212.40.185.200]:1182 "EHLO smtp-out-188.synserver.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753271AbbJTJqq (ORCPT ); Tue, 20 Oct 2015 05:46:46 -0400 X-SynServer-TrustedSrc: 1 X-SynServer-AuthUser: lars@metafoo.de X-SynServer-PPID: 2410 From: Lars-Peter Clausen To: Vinod Koul , Takashi Iwai Cc: Dan Williams , Russell King , Laurent Pinchart , Kuninori Morimoto , Qiao Zhou , Shengjiu Wang , Matt Campbell , Jonah Petri , dmaengine@vger.kernel.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, Lars-Peter Clausen Subject: [PATCH 4/4] ALSA: pcm_dmaengine: Properly synchronize DMA on shutdown Date: Tue, 20 Oct 2015 11:46:31 +0200 Message-Id: <1445334391-12272-5-git-send-email-lars@metafoo.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1445334391-12272-1-git-send-email-lars@metafoo.de> References: <1445334391-12272-1-git-send-email-lars@metafoo.de> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Use the new dmaengine_synchronize() function to make sure that all complete callbacks have finished running before the runtime data, which is accessed in the completed callback, is freed. This fixes a long standing use-after-free race condition that has been observed on some systems. Signed-off-by: Lars-Peter Clausen --- sound/core/pcm_dmaengine.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index fba365a..697c166 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -202,13 +202,13 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) if (runtime->info & SNDRV_PCM_INFO_PAUSE) dmaengine_pause(prtd->dma_chan); else - dmaengine_terminate_all(prtd->dma_chan); + dmaengine_terminate_async(prtd->dma_chan); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dmaengine_pause(prtd->dma_chan); break; case SNDRV_PCM_TRIGGER_STOP: - dmaengine_terminate_all(prtd->dma_chan); + dmaengine_terminate_async(prtd->dma_chan); break; default: return -EINVAL; @@ -346,6 +346,7 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + dmaengine_synchronize(prtd->dma_chan); kfree(prtd); return 0; @@ -362,9 +363,11 @@ int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + dmaengine_synchronize(prtd->dma_chan); dma_release_channel(prtd->dma_chan); + kfree(prtd); - return snd_dmaengine_pcm_close(substream); + return 0; } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); -- 2.1.4