Fix cpu offline but cat scaling_cur_freq is the same as online bug.
Schspa Shi (2): cpufreq: Abort show()/store() for half-initialized policies cpufreq: make interface functions and lock holding state clear
drivers/cpufreq/cpufreq.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
From: Schspa Shi schspa@gmail.com
mainline inclusion from mainline-v5.19-rc1 commit d4627a287e251efed59f2b4bda82c5950768c963 category: bugfix 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...
--------------------------------
If policy initialization fails after the sysfs files are created, there is a possibility to end up running show()/store() callbacks for half-initialized policies, which may have unpredictable outcomes.
Abort show()/store() in such a case by making sure the policy is active.
Also dectivate the policy on such failures.
Signed-off-by: Schspa Shi schspa@gmail.com Acked-by: Viresh Kumar viresh.kumar@linaro.org [ rjw: Subject and 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 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 58342390966b..9897d842c8a4 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -946,13 +946,14 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); - ssize_t ret; + ssize_t ret = -EBUSY;
if (!fattr->show) return -EIO;
down_read(&policy->rwsem); - ret = fattr->show(policy, buf); + if (likely(!policy_is_inactive(policy))) + ret = fattr->show(policy, buf); up_read(&policy->rwsem);
return ret; @@ -963,7 +964,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); - ssize_t ret = -EINVAL; + ssize_t ret = -EBUSY;
if (!fattr->store) return -EIO; @@ -977,7 +978,8 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
if (cpu_online(policy->cpu)) { down_write(&policy->rwsem); - ret = fattr->store(policy, buf, count); + if (likely(!policy_is_inactive(policy))) + ret = fattr->store(policy, buf, count); up_write(&policy->rwsem); }
@@ -1515,6 +1517,7 @@ static int cpufreq_online(unsigned int cpu) for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, get_cpu_device(j));
+ cpumask_clear(policy->cpus); up_write(&policy->rwsem);
out_offline_policy:
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 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9897d842c8a4..70f7a638b6db 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1337,12 +1337,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); }
if (!new_policy && cpufreq_driver->online) { @@ -1382,7 +1382,6 @@ static int cpufreq_online(unsigned int cpu) cpumask_copy(policy->related_cpus, policy->cpus); }
- down_write(&policy->rwsem); /* * affected cpus must always be the one, which are online. We aren't * managing offline cpus here. @@ -1518,7 +1517,6 @@ 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_offline_policy: if (cpufreq_driver->offline) @@ -1529,6 +1527,8 @@ static int cpufreq_online(unsigned int cpu) cpufreq_driver->exit(policy);
out_free_policy: + up_write(&policy->rwsem); + cpufreq_policy_free(policy); return ret; }
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/2782 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/2782 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2...