From: Schspa Shi schspa@gmail.com
mainline inclusion from mainline-v5.19-rc1 commit 514ff1bcd98d7f57361025e2200b803d3ddde6c8 category: cleanup bugzilla: https://gitee.com/openeuler/kernel/issues/I8EI9L CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
cpufreq_offline() calls offline() and exit() under the policy rwsem But they are called outside the rwsem in cpufreq_online().
Make cpufreq_online() call offline() and exit() as well as online() and init() under the policy rwsem to achieve a clear lock relationship.
All of the init() and online() implementations in the tree only initialize the policy object without attempting to acquire the policy rwsem and they won't call cpufreq APIs attempting to acquire it.
Signed-off-by: Schspa Shi schspa@gmail.com Acked-by: Viresh Kumar viresh.kumar@linaro.org [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com
Conflicts: drivers/cpufreq/cpufreq.c
Signed-off-by: Jinjie Ruan ruanjinjie@huawei.com --- drivers/cpufreq/cpufreq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7e6076fba875..4bd9fc287c82 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1200,12 +1200,12 @@ static int cpufreq_online(unsigned int cpu) down_write(&policy->rwsem); policy->cpu = cpu; policy->governor = NULL; - up_write(&policy->rwsem); } else { new_policy = true; policy = cpufreq_policy_alloc(cpu); if (!policy) return -ENOMEM; + down_write(&policy->rwsem); }
cpumask_copy(policy->cpus, cpumask_of(cpu)); @@ -1223,8 +1223,6 @@ static int cpufreq_online(unsigned int cpu) if (ret) goto out_exit_policy;
- down_write(&policy->rwsem); - if (new_policy) { /* related_cpus should at least include policy->cpus. */ cpumask_copy(policy->related_cpus, policy->cpus); @@ -1335,13 +1333,14 @@ static int cpufreq_online(unsigned int cpu) remove_cpu_dev_symlink(policy, get_cpu_device(j));
cpumask_clear(policy->cpus); - up_write(&policy->rwsem);
out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy);
out_free_policy: + up_write(&policy->rwsem); + cpufreq_policy_free(policy); return ret; }