6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Ke make24@iscas.ac.cn
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 make24@iscas.ac.cn Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@oss.qualcomm.com Link: https://patch.msgid.link/20251116033716.29369-1-make24@iscas.ac.cn Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/soc/codecs/pm4125.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
--- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -1549,6 +1549,10 @@ static int pm4125_bind(struct device *de 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 *de 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 *de 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 *de 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 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); }