Patch "cpufreq: Fix possible race in cpufreq online error path" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    cpufreq: Fix possible race in cpufreq online error path

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     cpufreq-fix-possible-race-in-cpufreq-online-error-pa.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 79a54c63565a99823553200ed814ad797f826fe1
Author: Schspa Shi <schspa@xxxxxxxxx>
Date:   Thu Apr 21 03:15:41 2022 +0800

    cpufreq: Fix possible race in cpufreq online error path
    
    [ Upstream commit f346e96267cd76175d6c201b40f770c0116a8a04 ]
    
    When cpufreq online fails, the policy->cpus mask is not cleared and
    policy->rwsem is released too early, so the driver can be invoked
    via the cpuinfo_cur_freq sysfs attribute while its ->offline() or
    ->exit() callbacks are being run.
    
    Take policy->clk as an example:
    
    static int cpufreq_online(unsigned int cpu)
    {
      ...
      // policy->cpus != 0 at this time
      down_write(&policy->rwsem);
      ret = cpufreq_add_dev_interface(policy);
      up_write(&policy->rwsem);
    
      return 0;
    
    out_destroy_policy:
            for_each_cpu(j, policy->real_cpus)
                    remove_cpu_dev_symlink(policy, get_cpu_device(j));
        up_write(&policy->rwsem);
    ...
    out_exit_policy:
      if (cpufreq_driver->exit)
        cpufreq_driver->exit(policy);
          clk_put(policy->clk);
          // policy->clk is a wild pointer
    ...
                                        ^
                                        |
                                Another process access
                                __cpufreq_get
                                  cpufreq_verify_current_freq
                                    cpufreq_generic_get
                                      // acces wild pointer of policy->clk;
                                        |
                                        |
    out_offline_policy:                 |
      cpufreq_policy_free(policy);      |
        // deleted here, and will wait for no body reference
        cpufreq_policy_put_kobj(policy);
    }
    
    Address this by modifying cpufreq_online() to release policy->rwsem
    in the error path after the driver callbacks have run and to clear
    policy->cpus before releasing the semaphore.
    
    Fixes: 7106e02baed4 ("cpufreq: release policy->rwsem on error")
    Signed-off-by: Schspa Shi <schspa@xxxxxxxxx>
    [ rjw: Subject and changelog edits ]
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index cddf7e13c232..502245710ee0 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1528,8 +1528,6 @@ static int cpufreq_online(unsigned int cpu)
 	for_each_cpu(j, policy->real_cpus)
 		remove_cpu_dev_symlink(policy, get_cpu_device(j));
 
-	up_write(&policy->rwsem);
-
 out_offline_policy:
 	if (cpufreq_driver->offline)
 		cpufreq_driver->offline(policy);
@@ -1538,6 +1536,9 @@ static int cpufreq_online(unsigned int cpu)
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
 
+	cpumask_clear(policy->cpus);
+	up_write(&policy->rwsem);
+
 out_free_policy:
 	cpufreq_policy_free(policy);
 	return ret;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux