]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
Switch tests over to using .text.user
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 6 Mar 2017 11:41:10 +0000 (11:41 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 6 Mar 2017 13:45:14 +0000 (13:45 +0000)
... in preference to test_wants_user_mappings.  This involves duplicating the
stubs which need to be executed in user context, and moving them into
.text.user.

As a result, the tests become SMEP/SMAP-safe, even in cases were such settings
are leaked from Xen.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
tests/cpuid-faulting/main.c
tests/pv-iopl/main.c
tests/swint-emulation/lowlevel.S
tests/swint-emulation/lowlevel.h
tests/swint-emulation/main.c
tests/xsa-170/main.c
tests/xsa-196/main.c

index 27265766b7301e94764e0d7e3928a32a82a9f2a9..78f465231ac1009e9dac5bf7b0f475ea08102efb 100644 (file)
@@ -27,8 +27,6 @@
 
 const char test_title[] = "Guest CPUID Faulting support";
 
-bool test_wants_user_mappings = true;
-
 unsigned long stub_cpuid(void)
 {
     unsigned int fault = 0, tmp;
@@ -42,6 +40,19 @@ unsigned long stub_cpuid(void)
     return fault;
 }
 
+unsigned long __user_text stub_user_cpuid(void)
+{
+    unsigned int fault = 0, tmp;
+
+    asm volatile("1: cpuid; 2:"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=a" (tmp), "+D" (fault)
+                 : "a" (0)
+                 : "ebx", "ecx", "edx");
+
+    return fault;
+}
+
 unsigned long stub_fep_cpuid(void)
 {
     unsigned int fault = 0, tmp;
@@ -56,6 +67,20 @@ unsigned long stub_fep_cpuid(void)
     return fault;
 }
 
+unsigned long __user_text stub_user_fep_cpuid(void)
+{
+    unsigned int fault = 0, tmp;
+
+    asm volatile(_ASM_XEN_FEP
+                 "1: cpuid; 2:"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=a" (tmp), "+D" (fault)
+                 : "a" (0)
+                 : "ebx", "ecx", "edx");
+
+    return fault;
+}
+
 static void test_cpuid(bool exp_faulting)
 {
     /*
@@ -76,13 +101,13 @@ static void test_cpuid(bool exp_faulting)
     unsigned long exp = exp_faulting ? EXINFO_SYM(GP, 0) : 0;
     const char *exp_fail_str = exp_faulting ? "didn't fault" : "faulted";
 
-    if ( exec_user(stub_cpuid) != exp )
+    if ( exec_user(stub_user_cpuid) != exp )
         xtf_failure("Fail: user cpuid %s\n", exp_fail_str);
 
-    if ( IS_DEFINED(CONFIG_PV) && exec_user(stub_fep_cpuid) != exp )
+    if ( IS_DEFINED(CONFIG_PV) && exec_user(stub_user_fep_cpuid) != exp )
         xtf_failure("Fail: user pv cpuid %s\n", exp_fail_str);
 
-    if ( xtf_has_fep && exec_user(stub_fep_cpuid) != exp )
+    if ( xtf_has_fep && exec_user(stub_user_fep_cpuid) != exp )
         xtf_failure("Fail: user emulated cpuid %s\n", exp_fail_str);
 }
 
index 74f47b6f68065f26df2c53efa7928f89f8a24bd2..a17d1f8a891ee878bf0ce81673b55064b80dd770 100644 (file)
@@ -44,8 +44,6 @@
 
 const char test_title[] = "PV IOPL emulation";
 
-bool test_wants_user_mappings = true;
-
 /**
  * Execute @p fn at user privilege, folding @p iopl into the iret frame.
  */
@@ -58,6 +56,13 @@ static void stub_cli(void)
                   _ASM_EXTABLE(1b, 2b));
 }
 
+/** Stub CLI instruction with @#GP fixup. */
+static void __user_text stub_user_cli(void)
+{
+    asm volatile ("1: cli; 2:"
+                  _ASM_EXTABLE(1b, 2b));
+}
+
 /** Stub OUTB instruction with @#GP fixup. */
 static void stub_outb(void)
 {
@@ -66,15 +71,24 @@ static void stub_outb(void)
                   :: "a" (0));
 }
 
+/** Stub OUTB instruction with @#GP fixup. */
+static void __user_text stub_user_outb(void)
+{
+    asm volatile ("1: outb %b0, $0x80; 2:"
+                  _ASM_EXTABLE(1b, 2b)
+                  :: "a" (0));
+}
+
 static const struct insn
 {
     const char *name;
     void (*fn)(void);
+    void (*user_fn)(void);
 } /** Sequence of instructions to run. */
     insn_sequence[] =
 {
-    { "cli",  stub_cli,  },
-    { "outb", stub_outb, },
+    { "cli",  stub_cli,  stub_user_cli,  },
+    { "outb", stub_outb, stub_user_outb, },
 };
 
 static struct expectation
@@ -168,7 +182,7 @@ static void run_test(const struct test *t)
 
             /* Run insn in userspace. */
             expect(seq->name, 1, t->should_fault(1, iopl));
-            exec_user_with_iopl(seq->fn, iopl);
+            exec_user_with_iopl(seq->user_fn, iopl);
             check();
         }
     }
@@ -213,7 +227,7 @@ static const struct test hypercall =
     .should_fault = hypercall_should_fault,
 };
 
-static void nop(void){}
+static void __user_text nop(void){}
 static void vmassist_set_iopl(unsigned int iopl)
 {
     /*
index 799576400c61b4b2862b7b32c225be21291b6419..3be82e809c37814c2cd6ab2dfa9863da6f8ec94d 100644 (file)
@@ -5,10 +5,10 @@
 
         /* Macro to generate a single test function. */
         /* See lowlevel.h for a description of nomenclature. */
-.macro GEN_SINGLE insn, type
+.macro GEN_SINGLE name, insn, type
 
         /* Function label.  e.g. stub_int3_red(). */
-ENTRY(stub_\insn\()_\type)
+ENTRY(stub_\name\()_\type)
 
         .ifc \insn, into
             /* Ensure the overflow flag is set, to trigger 'into'. */
@@ -29,7 +29,7 @@ ENTRY(stub_\insn\()_\type)
         .endif
 
         /* Label where a fault should occur.  e.g. label_int3_red_fault. */
-GLOBAL(label_\insn\()_\type\()_fault)
+GLOBAL(label_\name\()_\type\()_fault)
 
         /*
          * Possibly insert a redundant prefix.
@@ -62,24 +62,24 @@ GLOBAL(label_\insn\()_\type\()_fault)
         .endif
 
         /* Label where a trap should occur.  e.g. label_int3_red_trap. */
-GLOBAL(label_\insn\()_\type\()_trap)
+GLOBAL(label_\name\()_\type\()_trap)
 
         /* Function return. */
         ret
 
         /* Fixup from fault label to trap label. */
-        _ASM_EXTABLE(label_\insn\()_\type\()_fault,
-                     label_\insn\()_\type\()_trap)
+        _ASM_EXTABLE(label_\name\()_\type\()_fault,
+                     label_\name\()_\type\()_trap)
 
-ENDFUNC(stub_\insn\()_\type)
+ENDFUNC(stub_\name\()_\type)
 .endm
 
         /* For a single instruction, generate each test variant. */
 .macro GEN_SEQUENCE insn
-        GEN_SINGLE \insn reg
-        GEN_SINGLE \insn red
-        GEN_SINGLE \insn force
-        GEN_SINGLE \insn forcered
+        GEN_SINGLE \insn \insn reg
+        GEN_SINGLE \insn \insn red
+        GEN_SINGLE \insn \insn force
+        GEN_SINGLE \insn \insn forcered
 .endm
 
         /* Generate test sequences for each instruction. */
@@ -89,6 +89,25 @@ GEN_SEQUENCE icebp
 GEN_SEQUENCE int_0x1
 GEN_SEQUENCE into
 
+.pushsection .text.user, "ax", @progbits
+
+        /* For a single instruction, generate each user test variant. */
+.macro GEN_SEQUENCE_USER insn
+        GEN_SINGLE user_\insn \insn reg
+        GEN_SINGLE user_\insn \insn red
+        GEN_SINGLE user_\insn \insn force
+        GEN_SINGLE user_\insn \insn forcered
+.endm
+
+        /* Generate user test sequences for each instruction. */
+GEN_SEQUENCE_USER int3
+GEN_SEQUENCE_USER int_0x3
+GEN_SEQUENCE_USER icebp
+GEN_SEQUENCE_USER int_0x1
+GEN_SEQUENCE_USER into
+
+.popsection
+
 /*
  * Local variables:
  * tab-width: 8
index 1cbe8cb71a1204765383c5b65fb9e4090fe0d022..126e0b653be951f4f055b9e83961f5f7d7c09c4a 100644 (file)
@@ -8,6 +8,8 @@
  *   - Stub function executing instruction `$X` with prefix `$Y`.
  * - `label_$X_$Y_{trap, fault}:`
  *   - Labels for where `$X` is expected to trap or fault.
+ * - `{stub,label}_user_*`
+ *   - Stubs/labels in user mappings.
  *
  * Instructions `$X`:
  * - int3
@@ -79,6 +81,51 @@ extern unsigned long label_into_red_trap[], label_into_red_fault[];
 extern unsigned long label_into_force_trap[], label_into_force_fault[];
 extern unsigned long label_into_forcered_trap[], label_into_forcered_fault[];
 
+void stub_user_int3_reg(void);
+void stub_user_int3_red(void);
+void stub_user_int3_force(void);
+void stub_user_int3_forcered(void);
+extern unsigned long label_user_int3_reg_trap[], label_user_int3_reg_fault[];
+extern unsigned long label_user_int3_red_trap[], label_user_int3_red_fault[];
+extern unsigned long label_user_int3_force_trap[], label_user_int3_force_fault[];
+extern unsigned long label_user_int3_forcered_trap[], label_user_int3_forcered_fault[];
+
+void stub_user_int_0x3_reg(void);
+void stub_user_int_0x3_red(void);
+void stub_user_int_0x3_force(void);
+void stub_user_int_0x3_forcered(void);
+extern unsigned long label_user_int_0x3_reg_trap[], label_user_int_0x3_reg_fault[];
+extern unsigned long label_user_int_0x3_red_trap[], label_user_int_0x3_red_fault[];
+extern unsigned long label_user_int_0x3_force_trap[], label_user_int_0x3_force_fault[];
+extern unsigned long label_user_int_0x3_forcered_trap[], label_user_int_0x3_forcered_fault[];
+
+void stub_user_icebp_reg(void);
+void stub_user_icebp_red(void);
+void stub_user_icebp_force(void);
+void stub_user_icebp_forcered(void);
+extern unsigned long label_user_icebp_reg_trap[], label_user_icebp_reg_fault[];
+extern unsigned long label_user_icebp_red_trap[], label_user_icebp_red_fault[];
+extern unsigned long label_user_icebp_force_trap[], label_user_icebp_force_fault[];
+extern unsigned long label_user_icebp_forcered_trap[], label_user_icebp_forcered_fault[];
+
+void stub_user_int_0x1_reg(void);
+void stub_user_int_0x1_red(void);
+void stub_user_int_0x1_force(void);
+void stub_user_int_0x1_forcered(void);
+extern unsigned long label_user_int_0x1_reg_trap[], label_user_int_0x1_reg_fault[];
+extern unsigned long label_user_int_0x1_red_trap[], label_user_int_0x1_red_fault[];
+extern unsigned long label_user_int_0x1_force_trap[], label_user_int_0x1_force_fault[];
+extern unsigned long label_user_int_0x1_forcered_trap[], label_user_int_0x1_forcered_fault[];
+
+void stub_user_into_reg(void);
+void stub_user_into_red(void);
+void stub_user_into_force(void);
+void stub_user_into_forcered(void);
+extern unsigned long label_user_into_reg_trap[], label_user_into_reg_fault[];
+extern unsigned long label_user_into_red_trap[], label_user_into_red_fault[];
+extern unsigned long label_user_into_force_trap[], label_user_into_force_fault[];
+extern unsigned long label_user_into_forcered_trap[], label_user_into_forcered_fault[];
+
 #endif /* __LOWLEVEL_H__ */
 
 /*
index 0fb8352df07bbca575d291b6eca40235c9b4eb97..011a6c418b8d7c68f13b06e4b7b6894efefb9854 100644 (file)
 
 const char test_title[] = "Software interrupt emulation";
 
-bool test_wants_user_mappings = true;
-
 /** Single stub's worth of information. */
 struct single
 {
     const char *type;
     void (*fn)(void);
     void *trap, *fault;
+
+    void (*user_fn)(void);
+    void *user_trap, *user_fault;
 };
 
 /** A collection of subs for an instruction. */
@@ -75,16 +76,32 @@ struct sequence int3 =
 { "int3",
   {
       {"regular", stub_int3_reg,
-       label_int3_reg_trap, label_int3_reg_fault},
+       label_int3_reg_trap, label_int3_reg_fault,
+
+       stub_user_int3_reg,
+       label_user_int3_reg_trap, label_user_int3_reg_fault,
+      },
 
       {"redundant", stub_int3_red,
-       label_int3_red_trap, label_int3_red_fault},
+       label_int3_red_trap, label_int3_red_fault,
+
+       stub_user_int3_red,
+       label_user_int3_red_trap, label_user_int3_red_fault,
+      },
 
       {"forced", stub_int3_force,
-       label_int3_force_trap, label_int3_force_fault},
+       label_int3_force_trap, label_int3_force_fault,
+
+       stub_user_int3_force,
+       label_user_int3_force_trap, label_user_int3_force_fault,
+      },
 
       {"forced redundant", stub_int3_forcered,
-       label_int3_forcered_trap, label_int3_forcered_fault},
+       label_int3_forcered_trap, label_int3_forcered_fault,
+
+       stub_user_int3_forcered,
+       label_user_int3_forcered_trap, label_user_int3_forcered_fault,
+      },
   },
 };
 
@@ -93,16 +110,32 @@ struct sequence int_0x3 =
 { "int $3",
   {
       {"regular", stub_int_0x3_reg,
-       label_int_0x3_reg_trap, label_int_0x3_reg_fault},
+       label_int_0x3_reg_trap, label_int_0x3_reg_fault,
+
+       stub_user_int_0x3_reg,
+       label_user_int_0x3_reg_trap, label_user_int_0x3_reg_fault,
+      },
 
       {"redundant", stub_int_0x3_red,
-       label_int_0x3_red_trap, label_int_0x3_red_fault},
+       label_int_0x3_red_trap, label_int_0x3_red_fault,
+
+       stub_user_int_0x3_red,
+       label_user_int_0x3_red_trap, label_user_int_0x3_red_fault,
+      },
 
       {"forced", stub_int_0x3_force,
-       label_int_0x3_force_trap, label_int_0x3_force_fault},
+       label_int_0x3_force_trap, label_int_0x3_force_fault,
+
+       stub_user_int_0x3_force,
+       label_user_int_0x3_force_trap, label_user_int_0x3_force_fault,
+      },
 
       {"forced redundant", stub_int_0x3_forcered,
-       label_int_0x3_forcered_trap, label_int_0x3_forcered_fault},
+       label_int_0x3_forcered_trap, label_int_0x3_forcered_fault,
+
+       stub_user_int_0x3_forcered,
+       label_user_int_0x3_forcered_trap, label_user_int_0x3_forcered_fault,
+      },
   },
 };
 
@@ -111,16 +144,32 @@ struct sequence icebp =
 { "icebp",
   {
       {"regular", stub_icebp_reg,
-       label_icebp_reg_trap, label_icebp_reg_fault},
+       label_icebp_reg_trap, label_icebp_reg_fault,
+
+       stub_user_icebp_reg,
+       label_user_icebp_reg_trap, label_user_icebp_reg_fault,
+      },
 
       {"redundant", stub_icebp_red,
-       label_icebp_red_trap, label_icebp_red_fault},
+       label_icebp_red_trap, label_icebp_red_fault,
+
+       stub_user_icebp_red,
+       label_user_icebp_red_trap, label_user_icebp_red_fault,
+      },
 
       {"forced", stub_icebp_force,
-       label_icebp_force_trap, label_icebp_force_fault},
+       label_icebp_force_trap, label_icebp_force_fault,
+
+       stub_user_icebp_force,
+       label_user_icebp_force_trap, label_user_icebp_force_fault,
+      },
 
       {"forced redundant", stub_icebp_forcered,
-       label_icebp_forcered_trap, label_icebp_forcered_fault},
+       label_icebp_forcered_trap, label_icebp_forcered_fault,
+
+       stub_user_icebp_forcered,
+       label_user_icebp_forcered_trap, label_user_icebp_forcered_fault,
+      },
   },
 };
 
@@ -129,16 +178,32 @@ struct sequence int_0x1 =
 { "int $1",
   {
       {"regular", stub_int_0x1_reg,
-       label_int_0x1_reg_trap, label_int_0x1_reg_fault},
+       label_int_0x1_reg_trap, label_int_0x1_reg_fault,
+
+       stub_user_int_0x1_reg,
+       label_user_int_0x1_reg_trap, label_user_int_0x1_reg_fault
+      },
 
       {"redundant", stub_int_0x1_red,
-       label_int_0x1_red_trap, label_int_0x1_red_fault},
+       label_int_0x1_red_trap, label_int_0x1_red_fault,
+
+       stub_user_int_0x1_red,
+       label_user_int_0x1_red_trap, label_user_int_0x1_red_fault,
+      },
 
       {"forced", stub_int_0x1_force,
-       label_int_0x1_force_trap, label_int_0x1_force_fault},
+       label_int_0x1_force_trap, label_int_0x1_force_fault,
+
+       stub_user_int_0x1_force,
+       label_user_int_0x1_force_trap, label_user_int_0x1_force_fault,
+      },
 
       {"forced redundant", stub_int_0x1_forcered,
-       label_int_0x1_forcered_trap, label_int_0x1_forcered_fault},
+       label_int_0x1_forcered_trap, label_int_0x1_forcered_fault,
+
+       stub_user_int_0x1_forcered,
+       label_user_int_0x1_forcered_trap, label_user_int_0x1_forcered_fault,
+      },
   },
 };
 
@@ -147,16 +212,32 @@ struct sequence into =
 { "into",
   {
       {"regular", stub_into_reg,
-       label_into_reg_trap, label_into_reg_fault},
+       label_into_reg_trap, label_into_reg_fault,
+
+       stub_user_into_reg,
+       label_user_into_reg_trap, label_user_into_reg_fault,
+      },
 
       {"redundant", stub_into_red,
-       label_into_red_trap, label_into_red_fault},
+       label_into_red_trap, label_into_red_fault,
+
+       stub_user_into_red,
+       label_user_into_red_trap, label_user_into_red_fault,
+      },
 
       {"forced", stub_into_force,
-       label_into_force_trap, label_into_force_fault},
+       label_into_force_trap, label_into_force_fault,
+
+       stub_user_into_force,
+       label_user_into_force_trap, label_user_into_force_fault,
+      },
 
       {"forced redundant", stub_into_forcered,
-       label_into_forcered_trap, label_into_forcered_fault},
+       label_into_forcered_trap, label_into_forcered_fault,
+
+       stub_user_into_forcered,
+       label_user_into_forcered_trap, label_user_into_forcered_fault,
+      },
   },
 };
 
@@ -234,12 +315,16 @@ void test_seq(struct sequence *seq, unsigned int vector,
     for ( i = 0; i < ARRAY_SIZE(seq->tests); ++i )
     {
         struct single *s = &seq->tests[i];
+        void *addr;
+
+        if ( user )
+            addr = fault ? s->user_fault : s->user_trap;
+        else
+            addr = fault ? s->fault : s->trap;
 
-        expect(s->type,
-               fault ? s->fault : s->trap,
-               vector, error);
+        expect(s->type, addr, vector, error);
 
-        user ? exec_user_void(s->fn) : s->fn();
+        user ? exec_user_void(s->user_fn) : s->fn();
 
         check();
 
index c8fbf18b85805bcab27d46c33251ad74dae51030..bb79336d55420757d86fd59e74680d7d89de776c 100644 (file)
 
 const char test_title[] = "XSA-170 PoC";
 
-bool test_wants_user_mappings = true;
 bool test_needs_fep = true;
 
-void wild_jump(void)
+void __user_text wild_jump(void)
 {
     /*
      * After XSA-170, Xen's instruction emulator was improved to perform a
@@ -45,7 +44,7 @@ void wild_jump(void)
                   :: "qI" (0x8000000000000000ULL));
 }
 
-void nop_slide(void)
+void __user_text nop_slide(void)
 {
     /*
      * AMD hardware can correctly re-enter the guest with a non-canonical
index 4a0ec1294809098e11d403c30aa500947e51cf8d..7d1331efcae510fb9488dd083a71a7846918f2f7 100644 (file)
@@ -31,7 +31,6 @@
 
 const char test_title[] = "XSA-196 PoC";
 
-bool test_wants_user_mappings = true;
 bool test_needs_fep = true;
 
 void custom_doublefault_handler(void);
@@ -42,7 +41,7 @@ asm(".align 16;"
     "iretq;"
     );
 
-unsigned long compat_userspace(void)
+static unsigned long __user_text compat_userspace(void)
 {
     exinfo_t fault = 0;