]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: sdw_utils: fix device reference leak in is_sdca_endpoint_present()
authorMiaoqian Lin <linmq006@gmail.com>
Wed, 29 Oct 2025 07:17:58 +0000 (15:17 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 6 Nov 2025 13:12:33 +0000 (13:12 +0000)
The bus_find_device_by_name() function returns a device pointer with an
incremented reference count, but the original code was missing put_device()
calls in some return paths, leading to reference count leaks.

Fix this by ensuring put_device() is called before function exit after
  bus_find_device_by_name() succeeds

This follows the same pattern used elsewhere in the kernel where
bus_find_device_by_name() is properly paired with put_device().

Found via static analysis and code review.

Fixes: 4f8ef33dd44a ("ASoC: soc_sdw_utils: skip the endpoint that doesn't present")
Cc: stable@vger.kernel.org
Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
Link: https://patch.msgid.link/20251029071804.8425-1-linmq006@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sdw_utils/soc_sdw_utils.c

index f7c8c16308dea994d2867cd6542ce30b798dfbc9..3848c7df1916f08de78ade3cedc742ee8682bcbd 100644 (file)
@@ -1277,7 +1277,7 @@ static int is_sdca_endpoint_present(struct device *dev,
        struct sdw_slave *slave;
        struct device *sdw_dev;
        const char *sdw_codec_name;
-       int i;
+       int ret, i;
 
        dlc = kzalloc(sizeof(*dlc), GFP_KERNEL);
        if (!dlc)
@@ -1307,13 +1307,16 @@ static int is_sdca_endpoint_present(struct device *dev,
        }
 
        slave = dev_to_sdw_dev(sdw_dev);
-       if (!slave)
-               return -EINVAL;
+       if (!slave) {
+               ret = -EINVAL;
+               goto put_device;
+       }
 
        /* Make sure BIOS provides SDCA properties */
        if (!slave->sdca_data.interface_revision) {
                dev_warn(&slave->dev, "SDCA properties not found in the BIOS\n");
-               return 1;
+               ret = 1;
+               goto put_device;
        }
 
        for (i = 0; i < slave->sdca_data.num_functions; i++) {
@@ -1322,7 +1325,8 @@ static int is_sdca_endpoint_present(struct device *dev,
                if (dai_type == dai_info->dai_type) {
                        dev_dbg(&slave->dev, "DAI type %d sdca function %s found\n",
                                dai_type, slave->sdca_data.function[i].name);
-                       return 1;
+                       ret = 1;
+                       goto put_device;
                }
        }
 
@@ -1330,7 +1334,11 @@ static int is_sdca_endpoint_present(struct device *dev,
                "SDCA device function for DAI type %d not supported, skip endpoint\n",
                dai_info->dai_type);
 
-       return 0;
+       ret = 0;
+
+put_device:
+       put_device(sdw_dev);
+       return ret;
 }
 
 int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,