]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bus: fsl-mc: Fix potential double device reference in fsl_mc_get_endpoint()
authorMa Ke <make24@iscas.ac.cn>
Thu, 17 Jul 2025 02:23:07 +0000 (10:23 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 19 Jul 2025 00:13:50 +0000 (17:13 -0700)
The fsl_mc_get_endpoint() function may call fsl_mc_device_lookup()
twice, which would increment the device's reference count twice if
both lookups find a device. This could lead to a reference count leak.

Found by code review.

Cc: stable@vger.kernel.org
Fixes: 1ac210d128ef ("bus: fsl-mc: add the fsl_mc_get_endpoint function")
Signed-off-by: Ma Ke <make24@iscas.ac.cn>
Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Fixes: 8567494cebe5 ("bus: fsl-mc: rescan devices if endpoint not found")
Link: https://patch.msgid.link/20250717022309.3339976-1-make24@iscas.ac.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/bus/fsl-mc/fsl-mc-bus.c

index 7671bd1585455183e2ae402c703e6b812a8071c9..c1c0a4759c7e4f290e0077819f95bcb05ca275d5 100644 (file)
@@ -943,6 +943,7 @@ struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev,
        struct fsl_mc_obj_desc endpoint_desc = {{ 0 }};
        struct dprc_endpoint endpoint1 = {{ 0 }};
        struct dprc_endpoint endpoint2 = {{ 0 }};
+       struct fsl_mc_bus *mc_bus;
        int state, err;
 
        mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
@@ -966,6 +967,8 @@ struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev,
        strcpy(endpoint_desc.type, endpoint2.type);
        endpoint_desc.id = endpoint2.id;
        endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev);
+       if (endpoint)
+               return endpoint;
 
        /*
         * We know that the device has an endpoint because we verified by
@@ -973,17 +976,13 @@ struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev,
         * yet discovered by the fsl-mc bus, thus the lookup returned NULL.
         * Force a rescan of the devices in this container and retry the lookup.
         */
-       if (!endpoint) {
-               struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
-
-               if (mutex_trylock(&mc_bus->scan_mutex)) {
-                       err = dprc_scan_objects(mc_bus_dev, true);
-                       mutex_unlock(&mc_bus->scan_mutex);
-               }
-
-               if (err < 0)
-                       return ERR_PTR(err);
+       mc_bus = to_fsl_mc_bus(mc_bus_dev);
+       if (mutex_trylock(&mc_bus->scan_mutex)) {
+               err = dprc_scan_objects(mc_bus_dev, true);
+               mutex_unlock(&mc_bus->scan_mutex);
        }
+       if (err < 0)
+               return ERR_PTR(err);
 
        endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev);
        /*