From f2c7bd17bef4138df442747874ef67d57575faed Mon Sep 17 00:00:00 2001 From: Sheetal Date: Thu, 27 Nov 2025 05:50:22 +0000 Subject: [PATCH] ASoC: tegra: Fix memory leak in OOT machine driver Fix a memory leak in the NVIDIA Tegra ASoC machine driver where allocated DAPM widget lists were never freed. The function dpcm_runtime_set_dai_fmt() calls snd_soc_dapm_dai_get_connected_widgets() which allocates memory for a widget list, but was returning without calling snd_soc_dapm_dai_free_widgets() to free this memory. The leak was detected by kmemleak: unreferenced object 0xffff00008fc7e300 (size 192): comm "alsactl", pid 812, jiffies 4294900395 backtrace: kmemleak_alloc+0xc0/0xe8 __kmalloc+0x2e0/0x4c8 snd_soc_dapm_dai_get_connected_widgets+0x108/0x2a0 Fix this by using snd_soc_dapm_dai_free_widgets() on success or failure to ensure the widget list is always freed before returning. Bug 5667057 Change-Id: Ied69968884fc0646a3041e54427736ff1fc232ac Signed-off-by: Sheetal Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3500426 (cherry picked from commit 14b3fc2296967968d5972054bff38cf1bf4b518e) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3502770 Reviewed-by: svcacv Reviewed-by: Sameer Pujar Reviewed-by: Mohan kumar GVS: buildbot_gerritrpt --- sound/soc/tegra/tegra_asoc_machine.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index a71db376..313d3132 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -52,17 +52,19 @@ static int dpcm_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, #else struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); #endif - struct snd_soc_dapm_widget_list *list; + struct snd_soc_dapm_widget_list *list = NULL; int stream = SNDRV_PCM_STREAM_PLAYBACK; struct snd_soc_pcm_runtime *be; struct snd_soc_dapm_widget *widget; - int i, ret; + int i, ret = 0; /* nothing to be done if it is a normal sound card */ if (!rtd->card->component_chaining) return 0; - snd_soc_dapm_dai_get_connected_widgets(dai, stream, &list, NULL); + ret = snd_soc_dapm_dai_get_connected_widgets(dai, stream, &list, NULL); + if (ret < 0) + return ret; for_each_dapm_widgets(list, i, widget) { if (widget->id != snd_soc_dapm_dai_in && @@ -75,10 +77,12 @@ static int dpcm_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_runtime_set_dai_fmt(be, fmt); if (ret < 0) - return ret; + goto out; } - return 0; +out: + snd_soc_dapm_dai_free_widgets(&list); + return ret; } static int tegra_machine_codec_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,