]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
coresight: platform: defer connection counter increment until alloc succeeds
authorJie Gan <jie.gan@oss.qualcomm.com>
Mon, 11 May 2026 04:19:18 +0000 (12:19 +0800)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Tue, 19 May 2026 13:24:55 +0000 (14:24 +0100)
coresight_add_out_conn() increments nr_outconns before calling
devm_krealloc_array() and again before devm_kmalloc(). If either
allocation fails, the counter is already bumped while the corresponding
array entry is NULL or uninitialized garbage.

coresight_add_in_conn() has the same problem with nr_inconns and
devm_krealloc_array().

In both cases the probe returns -ENOMEM, which causes
coresight_get_platform_data() to call coresight_release_platform_data()
for cleanup. That function iterates up to nr_outconns (or nr_inconns)
entries and dereferences each pointer unconditionally, hitting the NULL
or garbage entry and panicking instead of failing gracefully.

Fix by moving the counter increments to after all allocations succeed,
so the struct is always consistent on any error path.

Fixes: 3d4ff657e454 ("coresight: Dynamically add connections")
Fixes: e3f4e68797a9 ("coresight: Store in-connections as well as out-connections")
Signed-off-by: Jie Gan <jie.gan@oss.qualcomm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260511-fix-ref-count-issue-v1-1-99d647810d3c@oss.qualcomm.com
drivers/hwtracing/coresight/coresight-platform.c

index e337b6e2bf327c774be92806dc1353a934d688b2..93c2d075cad66fdef1bfca918e9533e9006c58e2 100644 (file)
@@ -45,9 +45,8 @@ coresight_add_out_conn(struct device *dev,
                }
        }
 
-       pdata->nr_outconns++;
        pdata->out_conns =
-               devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns,
+               devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns + 1,
                                    sizeof(*pdata->out_conns), GFP_KERNEL);
        if (!pdata->out_conns)
                return ERR_PTR(-ENOMEM);
@@ -63,7 +62,8 @@ coresight_add_out_conn(struct device *dev,
         * used right away.
         */
        *conn = *new_conn;
-       pdata->out_conns[pdata->nr_outconns - 1] = conn;
+       pdata->out_conns[pdata->nr_outconns] = conn;
+       pdata->nr_outconns++;
        return conn;
 }
 EXPORT_SYMBOL_GPL(coresight_add_out_conn);
@@ -86,13 +86,13 @@ int coresight_add_in_conn(struct coresight_connection *out_conn)
                        return 0;
                }
 
-       pdata->nr_inconns++;
        pdata->in_conns =
-               devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns,
+               devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns + 1,
                                    sizeof(*pdata->in_conns), GFP_KERNEL);
        if (!pdata->in_conns)
                return -ENOMEM;
-       pdata->in_conns[pdata->nr_inconns - 1] = out_conn;
+       pdata->in_conns[pdata->nr_inconns] = out_conn;
+       pdata->nr_inconns++;
        return 0;
 }
 EXPORT_SYMBOL_GPL(coresight_add_in_conn);