From patchwork Wed May 8 09:56:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 795522 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AC29EC04FFE for ; Wed, 8 May 2024 09:57:38 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 8CD9F868; Wed, 8 May 2024 11:57:25 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 8CD9F868 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1715162255; bh=Mzl7cdo6GRa6aNpW/krWz0eupxXUOn59BXxd1oj37jU=; h=From:To:CC:Subject:Date:List-Id:List-Archive:List-Help:List-Owner: List-Post:List-Subscribe:List-Unsubscribe:From; b=LrkpiEhgzoL6HfhHXYJ4oGalHrM2Nh6kBn0O9EOETtoSOpYJq0i54YEeAXezeHWZ7 uJnz7MdI4lIBlXJRuiNoF6vuMdXhLTw61jbYNgTy4BvUqmVJ1j2sVQMADb8nReZBni oEM0f+mnYcxCjYcScQwOVlc6RVgyfFMoy1uRs1Y0= Received: by alsa1.perex.cz (Postfix, from userid 50401) id 0D7A8F8057D; Wed, 8 May 2024 11:57:05 +0200 (CEST) Received: from mailman-core.alsa-project.org (mailman-core.alsa-project.org [10.254.200.10]) by alsa1.perex.cz (Postfix) with ESMTP id 3D58EF805A9; Wed, 8 May 2024 11:57:04 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id EC17FF8049C; Wed, 8 May 2024 11:56:45 +0200 (CEST) Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 8666EF8003A for ; Wed, 8 May 2024 11:56:33 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 8666EF8003A Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key, unprotected) header.d=cirrus.com header.i=@cirrus.com header.a=rsa-sha256 header.s=PODMain02222019 header.b=Fg7jsYSw Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4486vtiF026053; Wed, 8 May 2024 04:56:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h= from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding:content-type; s=PODMain02222019; bh=R vqf78UChrZfvXZe6KiazLJ3FLV6tQAjUMLVg1LWMFg=; b=Fg7jsYSw4SHm94xl0 Zp8ABoUQ5zaQmHAX8qlORJ8UKfWNSLqBE1Ylc1L3yva8nvIU9xSIMrWFVlA1dMkD 8fHukjg4ur5Isl6JTTerGZRAdZqbE6K4dU4gDsxOMlS+Y4RXpJ+GnfEn4lnHX5uB BF/m2xBTnZdsKdn6BodiNTV3UBkyJ4VQKxC5RYw0NLr83EaNNqOlRGTw8mLg640S My4J6fp+qK/7maYjcr4WysCkC6aA+aMUZso4nN9TlxNfov0Z9+xdNrfNhHRIjh0e lK1E9mUYW/hH3cZkiBx2O8hNr2CdeQKRttq+zZvCylOsdmm8hrkMc0Y7/+Uf1201 iSGFA== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3xyshernev-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 08 May 2024 04:56:31 -0500 (CDT) Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 8 May 2024 10:56:27 +0100 Received: from ediswmail9.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9 via Frontend Transport; Wed, 8 May 2024 10:56:27 +0100 Received: from ediswws06.ad.cirrus.com (ediswws06.ad.cirrus.com [198.90.208.18]) by ediswmail9.ad.cirrus.com (Postfix) with ESMTP id 0D943820244; Wed, 8 May 2024 09:56:27 +0000 (UTC) From: Richard Fitzgerald To: CC: , , , Subject: [PATCH] ALSA: hda/cs_dsp_ctl: Use private_free for control cleanup Date: Wed, 8 May 2024 10:56:27 +0100 Message-ID: <20240508095627.44476-1-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-Proofpoint-GUID: HpwR96T6fm9AdjatzGpyAfUF0IKJAH6v X-Proofpoint-ORIG-GUID: HpwR96T6fm9AdjatzGpyAfUF0IKJAH6v X-Proofpoint-Spam-Reason: safe Message-ID-Hash: F4HT3NZMV6U7GS3BVZUSJ4EZPW5MPIFJ X-Message-ID-Hash: F4HT3NZMV6U7GS3BVZUSJ4EZPW5MPIFJ X-MailFrom: prvs=2858927d68=rf@opensource.cirrus.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-alsa-devel.alsa-project.org-0; header-match-alsa-devel.alsa-project.org-1; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.9 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Use the control private_free callback to free the associated data block. This ensures that the memory won't leak, whatever way the control gets destroyed. The original implementation didn't actually remove the ALSA controls in hda_cs_dsp_control_remove(). It only freed the internal tracking structure. This meant it was possible to remove/unload the amp driver while leaving its ALSA controls still present in the soundcard. Obviously attempting to access them could cause segfaults or at least dereferencing stale pointers. Signed-off-by: Richard Fitzgerald Fixes: 3233b978af23 ("ALSA: hda: hda_cs_dsp_ctl: Add Library to support CS_DSP ALSA controls") --- This replaces my earlier "keep it simple" attempt at cleanup. I decided that implementing private_free is the only sensible way to fix the cleanup. --- sound/pci/hda/hda_cs_dsp_ctl.c | 47 ++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 463ca06036bf..9db45d7c17e5 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include "hda_cs_dsp_ctl.h" @@ -97,11 +98,23 @@ static unsigned int wmfw_convert_flags(unsigned int in) return out; } -static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) +static void hda_cs_dsp_free_kcontrol(struct snd_kcontrol *kctl) { + struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl); struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; + + /* NULL priv to prevent a double-free in hda_cs_dsp_control_remove() */ + cs_ctl->priv = NULL; + kfree(ctl); +} + +static void hda_cs_dsp_add_kcontrol(struct cs_dsp_coeff_ctl *cs_ctl, + const struct hda_cs_dsp_ctl_info *info, + const char *name) +{ struct snd_kcontrol_new kcontrol = {0}; struct snd_kcontrol *kctl; + struct hda_cs_dsp_coeff_ctl *ctl __free(kfree) = NULL; int ret = 0; if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) { @@ -110,6 +123,13 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char return; } + ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); + if (!ctl) + return; + + ctl->cs_ctl = cs_ctl; + ctl->card = info->card; + kcontrol.name = name; kcontrol.info = hda_cs_dsp_coeff_info; kcontrol.iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -117,20 +137,22 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char kcontrol.get = hda_cs_dsp_coeff_get; kcontrol.put = hda_cs_dsp_coeff_put; - /* Save ctl inside private_data, ctl is owned by cs_dsp, - * and will be freed when cs_dsp removes the control */ kctl = snd_ctl_new1(&kcontrol, (void *)ctl); if (!kctl) return; - ret = snd_ctl_add(ctl->card, kctl); + kctl->private_free = hda_cs_dsp_free_kcontrol; + ctl->kctl = kctl; + + /* snd_ctl_add() calls our private_free on error, which will kfree(ctl) */ + cs_ctl->priv = no_free_ptr(ctl); + ret = snd_ctl_add(info->card, kctl); if (ret) { dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret); return; } dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name); - ctl->kctl = kctl; } static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, @@ -138,7 +160,6 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, { struct cs_dsp *cs_dsp = cs_ctl->dsp; char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - struct hda_cs_dsp_coeff_ctl *ctl; const char *region_name; int ret; @@ -163,15 +184,7 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip); } - ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); - if (!ctl) - return; - - ctl->cs_ctl = cs_ctl; - ctl->card = info->card; - cs_ctl->priv = ctl; - - hda_cs_dsp_add_kcontrol(ctl, name); + hda_cs_dsp_add_kcontrol(cs_ctl, info, name); } void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info) @@ -203,7 +216,9 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) { struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv; - kfree(ctl); + /* ctl and kctl may already have been removed by ALSA private_free */ + if (ctl && ctl->kctl) + snd_ctl_remove(ctl->card, ctl->kctl); } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS);