stable inclusion category: bugfix bugzilla: NA CVE: NA
In line 153 (#1), cpufreq_cpu_get() increments the kobject reference counter of the policy it returned on success. According to the document, the policy returned by cpufreq_cpu_get() has to be released with the help of cpufreq_cpu_put() to balance its kobject reference counter properly. Forgetting the cpufreq_cpu_put() operation will result in reference leak.This bug influences all stable versions from v5.15 to v5.15.7.
We can fix it by calling cpufreq_cpu_put() before the function returns (#2, #3 and #4).
147 static int cpuhp_dtpm_cpu_offline(unsigned int cpu) 148 { 153 policy = cpufreq_cpu_get(cpu); // #1: reference increment
155 if (!policy) 156 return 0;
158 pd = em_cpu_get(cpu); 159 if (!pd) 160 return -EINVAL; // #2: missing reference decrement
166 if (cpumask_weight(policy->cpus) != 1) 167 return 0; // #3: missing reference decrement
174 return 0; // #4: missing reference decrement 175 }
Signed-off-by: Jianglei Nie niejianglei2021@163.com --- drivers/powercap/dtpm_cpu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 51c366938acd..6c94515b21ef 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -156,21 +156,25 @@ static int cpuhp_dtpm_cpu_offline(unsigned int cpu) return 0;
pd = em_cpu_get(cpu); - if (!pd) + if (!pd) { + cpufreq_cpu_put(policy); return -EINVAL; + }
dtpm = per_cpu(dtpm_per_cpu, cpu);
power_sub(dtpm, pd);
- if (cpumask_weight(policy->cpus) != 1) + if (cpumask_weight(policy->cpus) != 1) { + cpufreq_cpu_put(policy); return 0; + }
for_each_cpu(cpu, policy->related_cpus) per_cpu(dtpm_per_cpu, cpu) = NULL;
dtpm_unregister(dtpm); - + cpufreq_cpu_put(policy); return 0; }