| From foo@baz Fri Mar 16 15:43:17 CET 2018 |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| Date: Thu, 23 Nov 2017 14:27:07 +0100 |
| Subject: cpufreq: Fix governor module removal race |
| |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| |
| |
| [ Upstream commit a8b149d32b663c1a4105273295184b78f53d33cf ] |
| |
| It is possible to remove a cpufreq governor module after |
| cpufreq_parse_governor() has returned success in |
| store_scaling_governor() and before cpufreq_set_policy() |
| acquires a reference to it, because the governor list is |
| not protected during that period and nothing prevents the |
| governor from being unregistered then. |
| |
| Prevent that from happening by acquiring an extra reference |
| to the governor module temporarily in cpufreq_parse_governor(), |
| under cpufreq_governor_mutex, and dropping it in |
| store_scaling_governor(), when cpufreq_set_policy() returns. |
| |
| Note that the second cpufreq_parse_governor() call site is fine, |
| because it only cares about the policy member of new_policy. |
| |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Acked-by: Viresh Kumar <viresh.kumar@linaro.org> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/cpufreq/cpufreq.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- a/drivers/cpufreq/cpufreq.c |
| +++ b/drivers/cpufreq/cpufreq.c |
| @@ -631,6 +631,8 @@ static int cpufreq_parse_governor(char * |
| *governor = t; |
| err = 0; |
| } |
| + if (t && !try_module_get(t->owner)) |
| + t = NULL; |
| |
| mutex_unlock(&cpufreq_governor_mutex); |
| } |
| @@ -759,6 +761,10 @@ static ssize_t store_scaling_governor(st |
| return -EINVAL; |
| |
| ret = cpufreq_set_policy(policy, &new_policy); |
| + |
| + if (new_policy.governor) |
| + module_put(new_policy.governor->owner); |
| + |
| return ret ? ret : count; |
| } |
| |