@@ -126,7 +126,7 @@ int __init cpufreq_register_governor(struct cpufreq_governor *governor)
int cpufreq_limit_change(unsigned int cpu)
{
- struct processor_performance *perf = &processor_pminfo[cpu]->perf;
+ struct processor_performance *perf;
struct cpufreq_policy *data;
struct cpufreq_policy policy;
@@ -134,6 +134,8 @@ int cpufreq_limit_change(unsigned int cpu)
!processor_pminfo[cpu])
return -ENODEV;
+ perf = &processor_pminfo[cpu]->perf;
+
if (perf->platform_limit >= perf->state_count)
return -EINVAL;
@@ -155,12 +157,15 @@ int cpufreq_add_cpu(unsigned int cpu)
struct cpufreq_dom *cpufreq_dom = NULL;
struct cpufreq_policy new_policy;
struct cpufreq_policy *policy;
- struct processor_performance *perf = &processor_pminfo[cpu]->perf;
+ struct processor_performance *perf;
/* to protect the case when Px was not controlled by xen */
- if (!processor_pminfo[cpu] ||
- !(perf->init & XEN_PX_INIT) ||
- !cpu_online(cpu))
+ if ( !processor_pminfo[cpu] || !cpu_online(cpu) )
+ return -EINVAL;
+
+ perf = &processor_pminfo[cpu]->perf;
+
+ if ( !(perf->init & XEN_PX_INIT) )
return -EINVAL;
if (!cpufreq_driver)
@@ -310,12 +315,15 @@ int cpufreq_del_cpu(unsigned int cpu)
struct list_head *pos;
struct cpufreq_dom *cpufreq_dom = NULL;
struct cpufreq_policy *policy;
- struct processor_performance *perf = &processor_pminfo[cpu]->perf;
+ struct processor_performance *perf;
/* to protect the case when Px was not controlled by xen */
- if (!processor_pminfo[cpu] ||
- !(perf->init & XEN_PX_INIT) ||
- !cpu_online(cpu))
+ if ( !processor_pminfo[cpu] || !cpu_online(cpu) )
+ return -EINVAL;
+
+ perf = &processor_pminfo[cpu]->perf;
+
+ if ( !(perf->init & XEN_PX_INIT) )
return -EINVAL;
if (!per_cpu(cpufreq_cpu_policy, cpu))
@@ -637,8 +645,6 @@ static struct notifier_block cpu_nfb = {
static int __init cpufreq_presmp_init(void)
{
- void *cpu = (void *)(long)smp_processor_id();
- cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb);
return 0;
}
The undefined behaviour sanitiser shows that it really is NULL via the pre_initcall path. (XEN) ================================================================================ (XEN) UBSAN: Undefined behaviour in cpufreq.c:158:66 (XEN) member access within null pointer of type 'struct processor_pminfo' (XEN) ----[ Xen-4.8-unstable x86_64 debug=y Not tainted ]---- <snip> (XEN) [<ffff82d0801c4231>] cpufreq_add_cpu+0x161/0xdc0 (XEN) [<ffff82d0801c6610>] cpufreq.c#cpu_callback+0x20/0x30 (XEN) [<ffff82d0804eefad>] cpufreq.c#cpufreq_presmp_init+0x2d/0x50 (XEN) [<ffff82d0804c5942>] do_presmp_initcalls+0x22/0x30 (XEN) [<ffff82d08051852d>] __start_xen+0x378d/0x42f0 (XEN) [<ffff82d080100073>] __high_start+0x53/0x60 Fix two other occurances of the same buggy logic. The processor_pminfo[] objects are only allocated as a result of XENPF_set_processor_pminfo hypercalls, which means that this early cpu callback will always hit the early NULL check, and is therefore pointless. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- CC: Jan Beulich <JBeulich@suse.com> --- xen/drivers/cpufreq/cpufreq.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)