From e616b2ba4d461a814d915aa721fcc675e31da321 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Thu, 28 Oct 2021 10:43:55 +0530 Subject: [PATCH] gpu: nvgpu: fix access-out-of-bounds issue As part of the function gp10b_clk_get_freqs, the code walksthrough the H/W frequency table and populates the gp10b_freq_table by picking only GP10B_NUM_SUPPORTED_FREQS = GP10B_MAX_SUPPORTED_FREQS/GP10B_FREQ_SELECT_STEP frequencies at max. The access-out-of-bounds happen when sel_freq_count reaches GP10B_NUM_SUPPORTED_FREQS and new_rate equals max_rate, resulting in one additional update that is beyond the size of gp10b_freq_table table. Also, removed the warning as it will never be true. Bug 3407276 Change-Id: Ic496ccdda1784130e7139bd93d068be58eb60a35 Signed-off-by: Debarshi Dutta Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2617850 Tested-by: mobile promotions Reviewed-by: svcacv Reviewed-by: Alex Waterman Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- .../gpu/nvgpu/os/linux/platform_gp10b_tegra.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c index 9c07c5159..35420453a 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_gp10b_tegra.c @@ -56,12 +56,15 @@ /* Select every GP10B_FREQ_SELECT_STEP'th frequency from h/w table */ #define GP10B_FREQ_SELECT_STEP 8 -/* Allow limited set of frequencies to be available */ -#define GP10B_NUM_SUPPORTED_FREQS 15 + /* Max number of freq supported in h/w */ #define GP10B_MAX_SUPPORTED_FREQS 120 + +/* Allow limited set of frequencies to be available */ +#define GP10B_NUM_SUPPORTED_FREQS ((GP10B_MAX_SUPPORTED_FREQS) / (GP10B_FREQ_SELECT_STEP)) + static unsigned long -gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS / GP10B_FREQ_SELECT_STEP]; +gp10b_freq_table[GP10B_NUM_SUPPORTED_FREQS]; static bool freq_table_init_complete; static int num_supported_freq; @@ -481,19 +484,18 @@ int gp10b_clk_get_freqs(struct device *dev, * add MAX freq to last */ sel_freq_cnt = 0; - for (i = 0; i < GP10B_MAX_SUPPORTED_FREQS; ++i) { + for (i = 0; i < GP10B_MAX_SUPPORTED_FREQS && + sel_freq_cnt < GP10B_NUM_SUPPORTED_FREQS; ++i) { new_rate = loc_freq_table[i]; - if (i % GP10B_FREQ_SELECT_STEP == 0 || + if ((i % GP10B_FREQ_SELECT_STEP == 0) || new_rate == max_rate) { - gp10b_freq_table[sel_freq_cnt++] = - new_rate; + gp10b_freq_table[sel_freq_cnt++] = new_rate; if (new_rate == max_rate) break; } } - WARN_ON(sel_freq_cnt == GP10B_MAX_SUPPORTED_FREQS); } /* Fill freq table */