• Schspa Shi's avatar
    cpufreq: Fix possible race in cpufreq online error path · f346e962
    Schspa Shi authored
    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: 7106e02b ("cpufreq: release policy->rwsem on error")
    Signed-off-by: default avatarSchspa Shi <schspa@gmail.com>
    [ rjw: Subject and changelog edits ]
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    f346e962
cpufreq.c 76.1 KB