From: Ma Ke Date: Sun, 16 Nov 2025 03:37:16 +0000 (+0800) Subject: ASoC: codecs: Fix error handling in pm4125 audio codec driver X-Git-Tag: v6.18.4~210 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=150352153ac9aa3fc995b94946dc7d897f0be354;p=thirdparty%2Fkernel%2Fstable.git ASoC: codecs: Fix error handling in pm4125 audio codec driver commit 2196e8172bee2002e9baaa0d02b2f9f2dd213949 upstream. pm4125_bind() acquires references through pm4125_sdw_device_get() but fails to release them in error paths and during normal unbind operations. This could result in reference count leaks, preventing proper cleanup and potentially causing resource exhaustion over multiple bind/unbind cycles. Calling path: pm4125_sdw_device_get() -> bus_find_device_by_of_node() -> bus_find_device() -> get_device. Found by code review. Cc: stable@vger.kernel.org Fixes: 8ad529484937 ("ASoC: codecs: add new pm4125 audio codec driver") Signed-off-by: Ma Ke Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20251116033716.29369-1-make24@iscas.ac.cn Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 3657a4a759855..3d7b07624ee61 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -1549,6 +1549,10 @@ static int pm4125_bind(struct device *dev) struct device_link *devlink; int ret; + /* Initialize device pointers to NULL for safe cleanup */ + pm4125->rxdev = NULL; + pm4125->txdev = NULL; + /* Give the soundwire subdevices some more time to settle */ usleep_range(15000, 15010); @@ -1572,7 +1576,7 @@ static int pm4125_bind(struct device *dev) if (!pm4125->txdev) { dev_err(dev, "could not find txslave with matching of node\n"); ret = -EINVAL; - goto error_unbind_all; + goto error_put_rx; } pm4125->sdw_priv[AIF1_CAP] = dev_get_drvdata(pm4125->txdev); @@ -1582,7 +1586,7 @@ static int pm4125_bind(struct device *dev) if (!pm4125->tx_sdw_dev) { dev_err(dev, "could not get txslave with matching of dev\n"); ret = -EINVAL; - goto error_unbind_all; + goto error_put_tx; } /* @@ -1594,7 +1598,7 @@ static int pm4125_bind(struct device *dev) if (!devlink) { dev_err(dev, "Could not devlink TX and RX\n"); ret = -EINVAL; - goto error_unbind_all; + goto error_put_tx; } devlink = device_link_add(dev, pm4125->txdev, @@ -1648,6 +1652,10 @@ link_remove_dev_tx: device_link_remove(dev, pm4125->txdev); link_remove_rx_tx: device_link_remove(pm4125->rxdev, pm4125->txdev); +error_put_tx: + put_device(pm4125->txdev); +error_put_rx: + put_device(pm4125->rxdev); error_unbind_all: component_unbind_all(dev, pm4125); return ret; @@ -1663,6 +1671,13 @@ static void pm4125_unbind(struct device *dev) device_link_remove(dev, pm4125->txdev); device_link_remove(dev, pm4125->rxdev); device_link_remove(pm4125->rxdev, pm4125->txdev); + + /* Release device references acquired in bind */ + if (pm4125->txdev) + put_device(pm4125->txdev); + if (pm4125->rxdev) + put_device(pm4125->rxdev); + component_unbind_all(dev, pm4125); }