cpufreq: Make cpufreq_quick_get() safe to call
authorRichard Cochran <rcochran@linutronix.de>
Fri, 11 Mar 2016 08:43:07 +0000 (09:43 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 18 Mar 2016 00:49:01 +0000 (01:49 +0100)
The function, cpufreq_quick_get, accesses the global 'cpufreq_driver' and
its fields without taking the associated lock, cpufreq_driver_lock.

Without the locking, nothing guarantees that 'cpufreq_driver' remains
consistent during the call.  This patch fixes the issue by taking the lock
before accessing the data structure.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/cpufreq.c

index 4c7825856eabebde799913257e936f12b29ec387..f870399f00b1c38a0d604bc7d1a2d2dc4c552a4f 100644 (file)
@@ -1401,9 +1401,17 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
 {
        struct cpufreq_policy *policy;
        unsigned int ret_freq = 0;
+       unsigned long flags;
 
-       if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
-               return cpufreq_driver->get(cpu);
+       read_lock_irqsave(&cpufreq_driver_lock, flags);
+
+       if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) {
+               ret_freq = cpufreq_driver->get(cpu);
+               read_unlock_irqrestore(&cpufreq_driver_lock, flags);
+               return ret_freq;
+       }
+
+       read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
        policy = cpufreq_cpu_get(cpu);
        if (policy) {