CNTKCTL_EL1 is used by the guest to control access to the timer from
userspace. It therefore needs to be save/restored by Xen as part of
the VCPU state.
By default Linux on ARM64 exposes the timer to userspace. Furthermore on
ARM64, Linux provides helpers in a VDSO (gettimeofday/__do_get_tspec)
that use the timer counter. Conversely, during CPU bring up, Xen will
set CNTKCTL_EL1 to 0 (i.e disallow timer access to the userspace). As
a result, currently, if dom0 has 1 VCPU which is migrated to another
PCPU, init might crash.
Alternatively, a guest (malicious or not) might decide to disable
access to the timer from userspace. If the register is not
save/restored, when a DOM0 VCPU runs again, a similar crash would
result.
Also, drop CNTKCTL_EL1 initialization in init_timer_interrupt. Xen
should let the guest deal with this register.
This is XSA-91 / CVE-2014-3125.
Reported-by: Chen Baozi <baozich@gmail.com>
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
p->arch.tpidr_el1 = READ_SYSREG(TPIDR_EL1);
/* Arch timer */
+ p->arch.cntkctl = READ_SYSREG32(CNTKCTL_EL1);
virt_timer_save(p);
if ( is_32bit_domain(p->domain) && cpu_has_thumbee )
/* This is could trigger an hardware interrupt from the virtual
* timer. The interrupt needs to be injected into the guest. */
+ WRITE_SYSREG32(n->arch.cntkctl, CNTKCTL_EL1);
virt_timer_restore(n);
}
{
/* Sensible defaults */
WRITE_SYSREG64(0, CNTVOFF_EL2); /* No VM-specific offset */
- WRITE_SYSREG32(0, CNTKCTL_EL1); /* No user-mode access */
#if USE_HYP_TIMER
/* Do not let the VMs program the physical timer, only read the physical counter */
WRITE_SYSREG32(CNTHCTL_PA, CNTHCTL_EL2);
spinlock_t lock;
} vgic;
+ /* Timer registers */
+ uint32_t cntkctl;
+
struct vtimer phys_timer;
struct vtimer virt_timer;
} __cacheline_aligned;