From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-co1nam03on0118.outbound.protection.outlook.com ([104.47.40.118]:6048 "EHLO NAM03-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1032198AbeCAP2x (ORCPT ); Thu, 1 Mar 2018 10:28:53 -0500 From: Sasha Levin To: "stable@vger.kernel.org" , "stable-commits@vger.kernel.org" CC: Takashi Iwai , Sasha Levin Subject: [added to the 4.1 stable tree] ALSA: aloop: Release cable upon open error path Date: Thu, 1 Mar 2018 15:23:54 +0000 Message-ID: <20180301152116.1486-137-alexander.levin@microsoft.com> References: <20180301152116.1486-1-alexander.levin@microsoft.com> In-Reply-To: <20180301152116.1486-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Takashi Iwai This patch has been added to the 4.1 stable tree. If you have any objections, please let us know. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [ Upstream commit 9685347aa0a5c2869058ca6ab79fd8e93084a67f ] The aloop runtime object and its assignment in the cable are left even when opening a substream fails. This doesn't mean any memory leak, but it still keeps the invalid pointer that may be referred by the another side of the cable spontaneously, which is a potential Oops cause. Clean up the cable assignment and the empty cable upon the error path properly. Fixes: 597603d615d2 ("ALSA: introduce the snd-aloop module for the PCM loop= back") Cc: Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/drivers/aloop.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 7f9126efc1e5..a9695fb1c5f3 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -658,12 +658,31 @@ static int rule_channels(struct snd_pcm_hw_params *pa= rams, return snd_interval_refine(hw_param_interval(params, rule->var), &t); } =20 +static void free_cable(struct snd_pcm_substream *substream) +{ + struct loopback *loopback =3D substream->private_data; + int dev =3D get_cable_index(substream); + struct loopback_cable *cable; + + cable =3D loopback->cables[substream->number][dev]; + if (!cable) + return; + if (cable->streams[!substream->stream]) { + /* other stream is still alive */ + cable->streams[substream->stream] =3D NULL; + } else { + /* free the cable */ + loopback->cables[substream->number][dev] =3D NULL; + kfree(cable); + } +} + static int loopback_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime =3D substream->runtime; struct loopback *loopback =3D substream->private_data; struct loopback_pcm *dpcm; - struct loopback_cable *cable; + struct loopback_cable *cable =3D NULL; int err =3D 0; int dev =3D get_cable_index(substream); =20 @@ -682,7 +701,6 @@ static int loopback_open(struct snd_pcm_substream *subs= tream) if (!cable) { cable =3D kzalloc(sizeof(*cable), GFP_KERNEL); if (!cable) { - kfree(dpcm); err =3D -ENOMEM; goto unlock; } @@ -724,6 +742,10 @@ static int loopback_open(struct snd_pcm_substream *sub= stream) else runtime->hw =3D cable->hw; unlock: + if (err < 0) { + free_cable(substream); + kfree(dpcm); + } mutex_unlock(&loopback->cable_lock); return err; } @@ -732,20 +754,10 @@ static int loopback_close(struct snd_pcm_substream *s= ubstream) { struct loopback *loopback =3D substream->private_data; struct loopback_pcm *dpcm =3D substream->runtime->private_data; - struct loopback_cable *cable; - int dev =3D get_cable_index(substream); =20 loopback_timer_stop(dpcm); mutex_lock(&loopback->cable_lock); - cable =3D loopback->cables[substream->number][dev]; - if (cable->streams[!substream->stream]) { - /* other stream is still alive */ - cable->streams[substream->stream] =3D NULL; - } else { - /* free the cable */ - loopback->cables[substream->number][dev] =3D NULL; - kfree(cable); - } + free_cable(substream); mutex_unlock(&loopback->cable_lock); return 0; } --=20 2.14.1