From 8531a63fc627b6b0cee855b642b42ecc5adfb7d6 Mon Sep 17 00:00:00 2001 From: Pekka Pessi Date: Tue, 6 Sep 2022 09:04:24 +0300 Subject: [PATCH] rtcpu: fix overflow in device tree code Check the device tree property size for overflows. Refactor code and remove extra pointer arithmetics. CID 491822 Bug 3745813 Change-Id: I2cc6d448ceea1e287da47577e249dcd27240e6a6 Signed-off-by: Pekka Pessi Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2844421 Reviewed-by: svcacv Reviewed-by: Semi Malinen Reviewed-by: Sachin Nikam GVS: Gerrit_Virtual_Submit --- drivers/platform/tegra/rtcpu/clk-group.c | 69 +++++++++++++----------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/platform/tegra/rtcpu/clk-group.c b/drivers/platform/tegra/rtcpu/clk-group.c index dbff0448..5b0ba9dc 100644 --- a/drivers/platform/tegra/rtcpu/clk-group.c +++ b/drivers/platform/tegra/rtcpu/clk-group.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include "clk-group.h" @@ -7,20 +7,21 @@ #include #include #include +#include #include struct camrtc_clk_group { struct device *device; - int nclocks; - struct clk **clocks; struct { struct clk *slow; struct clk *fast; } parents; + u32 nclocks; struct { + struct clk *clk; u32 slow; u32 fast; - } *rates; + } clocks[]; }; static void camrtc_clk_group_release(struct device *dev, void *res) @@ -29,8 +30,8 @@ static void camrtc_clk_group_release(struct device *dev, void *res) int i; for (i = 0; i < grp->nclocks; i++) { - if (grp->clocks[i]) - clk_put(grp->clocks[i]); + if (grp->clocks[i].clk) + clk_put(grp->clocks[i].clk); } if (grp->parents.slow) @@ -76,7 +77,7 @@ struct camrtc_clk_group *camrtc_clk_group_get( int nclocks; int nrates; int nparents; - int index; + u32 index; int ret; if (!dev || !dev->of_node) @@ -85,11 +86,14 @@ struct camrtc_clk_group *camrtc_clk_group_get( np = dev->of_node; nclocks = of_property_count_strings(np, "clock-names"); - if (nclocks < 0) + if (nclocks < 0 || nclocks > (S32_MAX / sizeof(grp->clocks[0]))) return ERR_PTR(-ENOENT); /* This has pairs of u32s: slow and fast rate for each clock */ nrates = of_property_count_u64_elems(np, "nvidia,clock-rates"); + /* of_property_count_elems_of_size() already complains about this */ + if (nrates < 0) + nrates = 0; nparents = of_count_phandle_with_args(np, "nvidia,clock-parents", "#clock-cells"); @@ -99,18 +103,15 @@ struct camrtc_clk_group *camrtc_clk_group_get( grp = devres_alloc(camrtc_clk_group_release, sizeof(*grp) + - nclocks * sizeof(grp->clocks[0]) + - nclocks * sizeof(grp->rates[0]), + nclocks * sizeof(grp->clocks[0]), GFP_KERNEL); if (!grp) return ERR_PTR(-ENOMEM); grp->nclocks = nclocks; grp->device = dev; - grp->clocks = (struct clk **)(grp + 1); - grp->rates = (void *)(grp->clocks + nclocks); - for (index = 0; index < grp->nclocks; index++) { + for (index = 0; index < nclocks; index++) { struct clk *clk; clk = of_clk_get(np, index); @@ -119,16 +120,16 @@ struct camrtc_clk_group *camrtc_clk_group_get( goto error; } - grp->clocks[index] = clk; + grp->clocks[index].clk = clk; if (index >= nrates) continue; if (of_property_read_u32_index(np, "nvidia,clock-rates", - 2 * index, &grp->rates[index].slow)) + 2 * index, &grp->clocks[index].slow)) dev_warn(dev, "clock-rates property not found\n"); if (of_property_read_u32_index(np, "nvidia,clock-rates", - 2 * index + 1, &grp->rates[index].fast)) + 2 * index + 1, &grp->clocks[index].fast)) dev_warn(dev, "clock-rates property not found\n"); } @@ -173,7 +174,7 @@ int camrtc_clk_group_enable(const struct camrtc_clk_group *grp) return -ENODEV; for (index = 0; index < grp->nclocks; index++) { - err = clk_prepare_enable(grp->clocks[index]); + err = clk_prepare_enable(grp->clocks[index].clk); if (err) { camrtc_clk_group_error(grp, "enable", index, err); return err; @@ -192,10 +193,22 @@ void camrtc_clk_group_disable(const struct camrtc_clk_group *grp) return; for (index = 0; index < grp->nclocks; index++) - clk_disable_unprepare(grp->clocks[index]); + clk_disable_unprepare(grp->clocks[index].clk); } EXPORT_SYMBOL_GPL(camrtc_clk_group_disable); +static void camrtc_clk_group_set_parent(const struct camrtc_clk_group *grp, + struct clk *parent) +{ + int index; + + if (IS_ERR_OR_NULL(parent)) + return; + + for (index = 0; index < grp->nclocks; index++) + clk_set_parent(grp->clocks[index].clk, parent); +} + int camrtc_clk_group_adjust_slow(const struct camrtc_clk_group *grp) { int index; @@ -204,17 +217,13 @@ int camrtc_clk_group_adjust_slow(const struct camrtc_clk_group *grp) return -ENODEV; for (index = 0; index < grp->nclocks; index++) { - u32 slow = grp->rates[index].slow; + u32 slow = grp->clocks[index].slow; if (slow != 0) - clk_set_rate(grp->clocks[index], slow); + clk_set_rate(grp->clocks[index].clk, slow); } - if (grp->parents.slow != NULL) { - for (index = 0; index < grp->nclocks; index++) - clk_set_parent(grp->clocks[index], - grp->parents.slow); - } + camrtc_clk_group_set_parent(grp, grp->parents.slow); return 0; } @@ -227,17 +236,13 @@ int camrtc_clk_group_adjust_fast(const struct camrtc_clk_group *grp) if (IS_ERR_OR_NULL(grp)) return -ENODEV; - if (grp->parents.fast != NULL) { - for (index = 0; index < grp->nclocks; index++) - clk_set_parent(grp->clocks[index], - grp->parents.fast); - } + camrtc_clk_group_set_parent(grp, grp->parents.fast); for (index = 0; index < grp->nclocks; index++) { - u32 fast = grp->rates[index].fast; + u32 fast = grp->clocks[index].fast; if (fast != 0) - clk_set_rate(grp->clocks[index], fast); + clk_set_rate(grp->clocks[index].clk, fast); } return 0;