# Commit 03bd8c3a70d101fc2f8f36f1e171b7594462a4cd
# Date 2018-01-05 19:57:08 +0000
# Author Andrew Cooper <andrew.cooper3@citrix.com>
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
x86/entry: Erase guest GPR state on entry to Xen

This reduces the number of code gadgets which can be attacked with arbitrary
guest-controlled GPR values.

This is part of XSA-254.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>

--- a/xen/arch/x86/x86_32/entry.S
+++ b/xen/arch/x86/x86_32/entry.S
@@ -161,6 +161,7 @@ ENTRY(hypercall)
         FIXUP_RING0_GUEST_STACK
         SAVE_ALL(1f,1f)
 1:      sti
+        movl  UREGS_eax(%esp),%eax
         GET_CURRENT(%ebx)
         cmpl  $NR_hypercalls,%eax
         jae   bad_hypercall
--- a/xen/arch/x86/x86_64/compat/entry.S
+++ b/xen/arch/x86/x86_64/compat/entry.S
@@ -21,10 +21,9 @@ ENTRY(compat_hypercall)
         je    1f
         movl  $0x82,%edi
         call  check_for_unexpected_msi
-        RESTORE_ALL
-        SAVE_ALL
 1:
 
+        LOAD_C_CLOBBERED compat=1
         GET_CURRENT(%rbx)
 
         cmpl  $NR_hypercalls,%eax
@@ -53,7 +52,7 @@ ENTRY(compat_hypercall)
         xchgl %ecx,%esi              /* Arg 2, Arg 4 */
         movl  %edx,%edx              /* Arg 3        */
         movl  %edi,%r8d              /* Arg 5        */
-        movl  %ebp,%r9d              /* Arg 6        */
+        movl  UREGS_rbp(%rsp),%r9d   /* Arg 6        */
         movl  UREGS_rbx(%rsp),%edi   /* Arg 1        */
 #define SHADOW_BYTES 0  /* No on-stack shadow state */
 #endif
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -192,7 +192,7 @@ ENTRY(syscall_enter)
         jz    switch_to_kernel
 
 /*hypercall:*/
-        movq  %r10,%rcx
+        LOAD_C_CLOBBERED cx=0
         cmpq  $NR_hypercalls,%rax
         jae   bad_hypercall
 #ifndef NDEBUG
--- a/xen/include/asm-x86/x86_32/asm_defns.h
+++ b/xen/include/asm-x86/x86_32/asm_defns.h
@@ -9,7 +9,8 @@
         movl  %esp,%ebp;                        \
         notl  %ebp
 #else
-#define SETUP_EXCEPTION_FRAME_POINTER
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        xor   %ebp, %ebp
 #endif
 
 #ifndef NDEBUG
@@ -30,14 +31,20 @@
         pushl %ebp;                                     \
         SETUP_EXCEPTION_FRAME_POINTER;                  \
         pushl %edi;                                     \
+        xor   %edi, %edi;                               \
         pushl %esi;                                     \
+        xor   %esi, %esi;                               \
         pushl %edx;                                     \
+        xor   %edx, %edx;                               \
         pushl %ecx;                                     \
-        pushl %ebx
+        xor   %ecx, %ecx;                               \
+        pushl %ebx;                                     \
+        xor   %ebx, %ebx
 
 #define SAVE_ALL_GPRS                                   \
         cld;                                            \
         pushl %eax;                                     \
+        xor   %eax, %eax;                               \
         SAVE_GPRS_NO_EAX
 
 /*
--- a/xen/include/asm-x86/x86_64/asm_defns.h
+++ b/xen/include/asm-x86/x86_64/asm_defns.h
@@ -9,7 +9,8 @@
         movq  %rsp,%rbp;                        \
         notq  %rbp
 #else
-#define SETUP_EXCEPTION_FRAME_POINTER
+#define SETUP_EXCEPTION_FRAME_POINTER           \
+        xor   %ebp, %ebp
 #endif
 
 #ifndef NDEBUG
@@ -29,21 +30,35 @@
 #define SAVE_ALL                                \
         cld;                                    \
         pushq %rdi;                             \
+        xor   %edi, %edi;                       \
         pushq %rsi;                             \
+        xor   %esi, %esi;                       \
         pushq %rdx;                             \
+        xor   %edx, %edx;                       \
         pushq %rcx;                             \
+        xor   %ecx, %ecx;                       \
         pushq %rax;                             \
+        xor   %eax, %eax;                       \
         pushq %r8;                              \
+        xor   %r8d, %r8d;                       \
         pushq %r9;                              \
+        xor   %r9d, %r9d;                       \
         pushq %r10;                             \
+        xor   %r10d, %r10d;                     \
         pushq %r11;                             \
+        xor   %r11d, %r11d;                     \
         pushq %rbx;                             \
+        xor   %ebx, %ebx;                       \
         pushq %rbp;                             \
         SETUP_EXCEPTION_FRAME_POINTER;          \
         pushq %r12;                             \
+        xor   %r12d, %r12d;                     \
         pushq %r13;                             \
+        xor   %r13d, %r13d;                     \
         pushq %r14;                             \
-        pushq %r15;
+        xor   %r14d, %r14d;                     \
+        pushq %r15;                             \
+        xor   %r15d, %r15d
 
 #define RESTORE_ALL                             \
         popq  %r15;                             \
@@ -62,6 +77,35 @@
         popq  %rsi;                             \
         popq  %rdi;
 
+#ifdef __ASSEMBLY__
+/*
+ * Reload registers not preserved by C code from frame.
+ *
+ * @compat: R8-R11 don't need reloading
+ *
+ * For the way it is used in RESTORE_ALL, this macro must preserve EFLAGS.ZF.
+ */
+.macro LOAD_C_CLOBBERED compat=0 cx=1
+.if !\compat
+        movq  UREGS_r11(%rsp),%r11
+.if \cx
+        movq  UREGS_r10(%rsp),%r10
+.else
+        movq  UREGS_r10(%rsp),%rcx
+.endif
+        movq  UREGS_r9(%rsp),%r9
+        movq  UREGS_r8(%rsp),%r8
+.endif
+        movq  UREGS_rax(%rsp),%rax
+.if \cx
+        movq  UREGS_rcx(%rsp),%rcx
+.endif
+        movq  UREGS_rdx(%rsp),%rdx
+        movq  UREGS_rsi(%rsp),%rsi
+        movq  UREGS_rdi(%rsp),%rdi
+.endm
+#endif
+
 #ifdef PERF_COUNTERS
 #define PERFC_INCR(_name,_idx,_cur)             \
         pushq _cur;                             \
