thermal: cpu_cooling: fix out of bounds access in time_in_idle
commit a53b8394ec3c67255928df6ee9cc99dd1cd452e3 upstream. In __cpufreq_cooling_register() we allocate the arrays for time_in_idle and time_in_idle_timestamp to be as big as the number of cpus in this cpufreq device. However, in get_load() we access this array using the cpu number as index, which can result in an out of bound access. Index time_in_idle{,_timestamp} using the index in the cpufreq_device's allowed_cpus mask, as we do for the load_cpu array in cpufreq_get_requested_power() Reported-by: Nicolas Boichat <drinkcat@chromium.org> Cc: Amit Daniel Kachhap <amit.kachhap@gmail.com> Cc: Zhang Rui <rui.zhang@intel.com> Cc: Eduardo Valentin <edubezval@gmail.com> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Javi Merino <javi.merino@arm.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b252f82aeb
commit
e6f54e7f57
1 changed files with 8 additions and 6 deletions
|
@ -377,26 +377,28 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device,
|
||||||
* get_load() - get load for a cpu since last updated
|
* get_load() - get load for a cpu since last updated
|
||||||
* @cpufreq_device: &struct cpufreq_cooling_device for this cpu
|
* @cpufreq_device: &struct cpufreq_cooling_device for this cpu
|
||||||
* @cpu: cpu number
|
* @cpu: cpu number
|
||||||
|
* @cpu_idx: index of the cpu in cpufreq_device->allowed_cpus
|
||||||
*
|
*
|
||||||
* Return: The average load of cpu @cpu in percentage since this
|
* Return: The average load of cpu @cpu in percentage since this
|
||||||
* function was last called.
|
* function was last called.
|
||||||
*/
|
*/
|
||||||
static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu)
|
static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
|
||||||
|
int cpu_idx)
|
||||||
{
|
{
|
||||||
u32 load;
|
u32 load;
|
||||||
u64 now, now_idle, delta_time, delta_idle;
|
u64 now, now_idle, delta_time, delta_idle;
|
||||||
|
|
||||||
now_idle = get_cpu_idle_time(cpu, &now, 0);
|
now_idle = get_cpu_idle_time(cpu, &now, 0);
|
||||||
delta_idle = now_idle - cpufreq_device->time_in_idle[cpu];
|
delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
|
||||||
delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu];
|
delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu_idx];
|
||||||
|
|
||||||
if (delta_time <= delta_idle)
|
if (delta_time <= delta_idle)
|
||||||
load = 0;
|
load = 0;
|
||||||
else
|
else
|
||||||
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
|
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
|
||||||
|
|
||||||
cpufreq_device->time_in_idle[cpu] = now_idle;
|
cpufreq_device->time_in_idle[cpu_idx] = now_idle;
|
||||||
cpufreq_device->time_in_idle_timestamp[cpu] = now;
|
cpufreq_device->time_in_idle_timestamp[cpu_idx] = now;
|
||||||
|
|
||||||
return load;
|
return load;
|
||||||
}
|
}
|
||||||
|
@ -598,7 +600,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
|
||||||
u32 load;
|
u32 load;
|
||||||
|
|
||||||
if (cpu_online(cpu))
|
if (cpu_online(cpu))
|
||||||
load = get_load(cpufreq_device, cpu);
|
load = get_load(cpufreq_device, cpu, i);
|
||||||
else
|
else
|
||||||
load = 0;
|
load = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue