| From 23196373efe6e071051d23da23c8efbced31e52d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 17 Dec 2025 14:21:22 +0000 |
| Subject: ARM: omap2: Fix reference count leaks in omap_control_init() |
| |
| From: Wentao Liang <vulab@iscas.ac.cn> |
| |
| [ Upstream commit 93a04ab480c8bbcb7d9004be139c538c8a0c1bc8 ] |
| |
| The of_get_child_by_name() function increments the reference count |
| of child nodes, causing multiple reference leaks in omap_control_init(): |
| |
| 1. scm_conf node never released in normal/error paths |
| 2. clocks node leak when checking existence |
| 3. Missing scm_conf release before np in error paths |
| |
| Fix these leaks by adding proper of_node_put() calls and separate error |
| handling. |
| |
| Fixes: e5b635742e98 ("ARM: OMAP2+: control: add syscon support for register accesses") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Wentao Liang <vulab@iscas.ac.cn> |
| Reviewed-by: Andreas Kemnade <andreas@kemnade.info> |
| Link: https://patch.msgid.link/20251217142122.1861292-1-vulab@iscas.ac.cn |
| Signed-off-by: Kevin Hilman <khilman@baylibre.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/arm/mach-omap2/control.c | 14 ++++++++++---- |
| 1 file changed, 10 insertions(+), 4 deletions(-) |
| |
| diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c |
| index c514a96022699..9042bbfaeb072 100644 |
| --- a/arch/arm/mach-omap2/control.c |
| +++ b/arch/arm/mach-omap2/control.c |
| @@ -793,7 +793,7 @@ int __init omap2_control_base_init(void) |
| */ |
| int __init omap_control_init(void) |
| { |
| - struct device_node *np, *scm_conf; |
| + struct device_node *np, *scm_conf, *clocks_node; |
| const struct of_device_id *match; |
| const struct omap_prcm_init_data *data; |
| int ret; |
| @@ -814,16 +814,19 @@ int __init omap_control_init(void) |
| |
| if (IS_ERR(syscon)) { |
| ret = PTR_ERR(syscon); |
| - goto of_node_put; |
| + goto err_put_scm_conf; |
| } |
| |
| - if (of_get_child_by_name(scm_conf, "clocks")) { |
| + clocks_node = of_get_child_by_name(scm_conf, "clocks"); |
| + if (clocks_node) { |
| + of_node_put(clocks_node); |
| ret = omap2_clk_provider_init(scm_conf, |
| data->index, |
| syscon, NULL); |
| if (ret) |
| - goto of_node_put; |
| + goto err_put_scm_conf; |
| } |
| + of_node_put(scm_conf); |
| } else { |
| /* No scm_conf found, direct access */ |
| ret = omap2_clk_provider_init(np, data->index, NULL, |
| @@ -841,6 +844,9 @@ int __init omap_control_init(void) |
| |
| return 0; |
| |
| +err_put_scm_conf: |
| + if (scm_conf) |
| + of_node_put(scm_conf); |
| of_node_put: |
| of_node_put(np); |
| return ret; |
| -- |
| 2.51.0 |
| |