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;