From 84ccf346ca98595b9a7dfb0a58e516404851d1c2 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Tue, 7 Nov 2023 08:40:41 +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 (cherry picked from commit ae440cc22fbe6ff75701e8d76564f15eae694428) --- 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: -- Gitee From 1bed52fe4d16561393b577fce9a128f42d811050 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Tue, 7 Nov 2023 08:40:42 +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 (cherry picked from commit b5f506af66958fb0b32fa2d99d0a6ed962ad4faf) --- 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; } -- Gitee