summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tsc_sync.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-12-01 13:26:58 +0100
committerThomas Gleixner <tglx@linutronix.de>2016-12-01 14:40:52 +0100
commit31f8a651fc5784a9e6f482be5ef0dd111a535e88 (patch)
tree3e1f3404a4e93e6453946390043aeda4bff190fc /arch/x86/kernel/tsc_sync.c
parentb836554386cc77f31ab43a8492a2587e0c51d51e (diff)
downloadlinux-31f8a651fc5784a9e6f482be5ef0dd111a535e88.tar.bz2
x86/tsc: Validate cpumask pointer before accessing it
0-day testing encountered a NULL pointer dereference in a cpumask access from tsc_store_and_check_tsc_adjust(). This happens when the function is called on the boot CPU and the topology masks are not yet available due to CPUMASK_OFFSTACK=y. Add a NULL pointer check for the mask pointer. If NULL it's safe to assume that the CPU is the boot CPU and the first one in the package. Fixes: 8b223bc7abe0 ("x86/tsc: Store and check TSC ADJUST MSR") Reported-by: kernel test robot <xiaolong.ye@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/tsc_sync.c')
-rw-r--r--arch/x86/kernel/tsc_sync.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index 8fde44f8cfec..a75f696011d5 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -84,6 +84,7 @@ bool tsc_store_and_check_tsc_adjust(void)
{
struct tsc_adjust *ref, *cur = this_cpu_ptr(&tsc_adjust);
unsigned int refcpu, cpu = smp_processor_id();
+ struct cpumask *mask;
s64 bootval;
if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
@@ -98,9 +99,11 @@ bool tsc_store_and_check_tsc_adjust(void)
* Check whether this CPU is the first in a package to come up. In
* this case do not check the boot value against another package
* because the package might have been physically hotplugged, where
- * TSC_ADJUST is expected to be different.
+ * TSC_ADJUST is expected to be different. When called on the boot
+ * CPU topology_core_cpumask() might not be available yet.
*/
- refcpu = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+ mask = topology_core_cpumask(cpu);
+ refcpu = mask ? cpumask_any_but(mask, cpu) : nr_cpu_ids;
if (refcpu >= nr_cpu_ids) {
/*