From c8c0484fc013ddfdca4a95f901423a3e4e7d2b13 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Tue, 7 Nov 2023 08:32:58 +0000 Subject: [PATCH 1/2] cpufreq: Abort show()/store() for half-initialized policies 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/?id=d4627a287e251efed59f2b4bda82c5950768c963 -------------------------------- 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 Acked-by: Viresh Kumar [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki Conflicts: drivers/cpufreq/cpufreq.c Signed-off-by: Jinjie Ruan --- 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 99ca9c50a88f..7e6076fba875 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -907,13 +907,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; @@ -924,7 +925,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; @@ -938,7 +939,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); } @@ -1332,6 +1334,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_exit_policy: -- Gitee From 8ce1fbb877893665196e7afab06586927fd879f6 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Tue, 7 Nov 2023 08:32:59 +0000 Subject: [PATCH 2/2] cpufreq: make interface functions and lock holding state clear 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/?id=514ff1bcd98d7f57361025e2200b803d3ddde6c8 -------------------------------- 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 Acked-by: Viresh Kumar [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki Conflicts: drivers/cpufreq/cpufreq.c Signed-off-by: Jinjie Ruan --- 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; } -- Gitee