Skip to content

Commit 14c8a41

Browse files
Andre-ARMvireshk
authored andcommitted
cpufreq: sun50i: prevent out-of-bounds access
A KASAN enabled kernel reports an out-of-bounds access when handling the nvmem cell in the sun50i cpufreq driver: ================================================================== BUG: KASAN: slab-out-of-bounds in sun50i_cpufreq_nvmem_probe+0x180/0x3d4 Read of size 4 at addr ffff000006bf31e0 by task kworker/u16:1/38 This is because the DT specifies the nvmem cell as covering only two bytes, but we use a u32 pointer to read the value. DTs for other SoCs indeed specify 4 bytes, so we cannot just shorten the variable to a u16. Fortunately nvmem_cell_read() allows to return the length of the nvmem cell, in bytes, so we can use that information to only access the valid portion of the data. To cover multiple cell sizes, use memcpy() to copy the information into a zeroed u32 buffer, then also make sure we always read the data in little endian fashion, as this is how the data is stored in the SID efuses. Fixes: 6cc4bcc ("cpufreq: sun50i: Refactor speed bin decoding") Reported-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Jernej Škrabec <jernej.skrabec@gmail.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent 0af2f6b commit 14c8a41

File tree

1 file changed

+12
-6
lines changed

1 file changed

+12
-6
lines changed

drivers/cpufreq/sun50i-cpufreq-nvmem.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,9 @@ static int sun50i_cpufreq_get_efuse(void)
194194
struct nvmem_cell *speedbin_nvmem;
195195
const struct of_device_id *match;
196196
struct device *cpu_dev;
197-
u32 *speedbin;
197+
void *speedbin_ptr;
198+
u32 speedbin = 0;
199+
size_t len;
198200
int ret;
199201

200202
cpu_dev = get_cpu_device(0);
@@ -217,14 +219,18 @@ static int sun50i_cpufreq_get_efuse(void)
217219
return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
218220
"Could not get nvmem cell\n");
219221

220-
speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
222+
speedbin_ptr = nvmem_cell_read(speedbin_nvmem, &len);
221223
nvmem_cell_put(speedbin_nvmem);
222-
if (IS_ERR(speedbin))
223-
return PTR_ERR(speedbin);
224+
if (IS_ERR(speedbin_ptr))
225+
return PTR_ERR(speedbin_ptr);
224226

225-
ret = opp_data->efuse_xlate(*speedbin);
227+
if (len <= 4)
228+
memcpy(&speedbin, speedbin_ptr, len);
229+
speedbin = le32_to_cpu(speedbin);
226230

227-
kfree(speedbin);
231+
ret = opp_data->efuse_xlate(speedbin);
232+
233+
kfree(speedbin_ptr);
228234

229235
return ret;
230236
};

0 commit comments

Comments
 (0)