|
|
4b77cf7 |
From: Jan Beulich <jbeulich@suse.com>
|
|
|
4b77cf7 |
Subject: x86/PV: writes of %fs and %gs base MSRs require canonical addresses
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
Commit c42494acb2 ("x86: fix FS/GS base handling when using the
|
|
|
4b77cf7 |
fsgsbase feature") replaced the use of wrmsr_safe() on these paths
|
|
|
4b77cf7 |
without recognizing that wr{f,g}sbase() use just wrmsrl() and that the
|
|
|
4b77cf7 |
WR{F,G}SBASE instructions also raise #GP for non-canonical input.
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
Similarly arch_set_info_guest() needs to prevent non-canonical
|
|
|
4b77cf7 |
addresses from getting stored into state later to be loaded by context
|
|
|
4b77cf7 |
switch code. For consistency also check stack pointers and LDT base.
|
|
|
4b77cf7 |
DR0..3, otoh, already get properly checked in set_debugreg() (albeit
|
|
|
4b77cf7 |
we discard the error there).
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
The SHADOW_GS_BASE check isn't strictly necessary, but I think we
|
|
|
4b77cf7 |
better avoid trying the WRMSR if we know it's going to fail.
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
This is XSA-193.
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
|
4b77cf7 |
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
|
4b77cf7 |
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
|
4b77cf7 |
|
|
|
4b77cf7 |
--- a/xen/arch/x86/domain.c
|
|
|
4b77cf7 |
+++ b/xen/arch/x86/domain.c
|
|
|
4b77cf7 |
@@ -741,7 +741,13 @@ int arch_set_info_guest(
|
|
|
4b77cf7 |
{
|
|
|
4b77cf7 |
if ( !compat )
|
|
|
4b77cf7 |
{
|
|
|
4b77cf7 |
- if ( !is_canonical_address(c.nat->user_regs.eip) ||
|
|
|
4b77cf7 |
+ if ( !is_canonical_address(c.nat->user_regs.rip) ||
|
|
|
4b77cf7 |
+ !is_canonical_address(c.nat->user_regs.rsp) ||
|
|
|
4b77cf7 |
+ !is_canonical_address(c.nat->kernel_sp) ||
|
|
|
4b77cf7 |
+ (c.nat->ldt_ents && !is_canonical_address(c.nat->ldt_base)) ||
|
|
|
4b77cf7 |
+ !is_canonical_address(c.nat->fs_base) ||
|
|
|
4b77cf7 |
+ !is_canonical_address(c.nat->gs_base_kernel) ||
|
|
|
4b77cf7 |
+ !is_canonical_address(c.nat->gs_base_user) ||
|
|
|
4b77cf7 |
!is_canonical_address(c.nat->event_callback_eip) ||
|
|
|
4b77cf7 |
!is_canonical_address(c.nat->syscall_callback_eip) ||
|
|
|
4b77cf7 |
!is_canonical_address(c.nat->failsafe_callback_eip) )
|
|
|
4b77cf7 |
--- a/xen/arch/x86/traps.c
|
|
|
4b77cf7 |
+++ b/xen/arch/x86/traps.c
|
|
|
4b77cf7 |
@@ -2439,19 +2439,19 @@ static int emulate_privileged_op(struct
|
|
|
4b77cf7 |
switch ( (u32)regs->ecx )
|
|
|
4b77cf7 |
{
|
|
|
4b77cf7 |
case MSR_FS_BASE:
|
|
|
4b77cf7 |
- if ( is_pv_32on64_vcpu(v) )
|
|
|
4b77cf7 |
+ if ( is_pv_32on64_vcpu(v) || !is_canonical_address(msr_content) )
|
|
|
4b77cf7 |
goto fail;
|
|
|
4b77cf7 |
wrfsbase(msr_content);
|
|
|
4b77cf7 |
v->arch.pv_vcpu.fs_base = msr_content;
|
|
|
4b77cf7 |
break;
|
|
|
4b77cf7 |
case MSR_GS_BASE:
|
|
|
4b77cf7 |
- if ( is_pv_32on64_vcpu(v) )
|
|
|
4b77cf7 |
+ if ( is_pv_32on64_vcpu(v) || !is_canonical_address(msr_content) )
|
|
|
4b77cf7 |
goto fail;
|
|
|
4b77cf7 |
wrgsbase(msr_content);
|
|
|
4b77cf7 |
v->arch.pv_vcpu.gs_base_kernel = msr_content;
|
|
|
4b77cf7 |
break;
|
|
|
4b77cf7 |
case MSR_SHADOW_GS_BASE:
|
|
|
4b77cf7 |
- if ( is_pv_32on64_vcpu(v) )
|
|
|
4b77cf7 |
+ if ( is_pv_32on64_vcpu(v) || !is_canonical_address(msr_content) )
|
|
|
4b77cf7 |
goto fail;
|
|
|
4b77cf7 |
if ( wrmsr_safe(MSR_SHADOW_GS_BASE, msr_content) )
|
|
|
4b77cf7 |
goto fail;
|