From e399b894f042d3f50d07a8619f7d7e7de410351d Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Tue, 11 Apr 2017 11:38:50 +0100 Subject: [PATCH] Pass _ASM_EXTABLE_HANDLER() references by asm() parameter ... rather than embedding a reference directly. This makes LTO aware of the reference (rather than finding no C-level references, dropping the functions and subsequently failing to link), and allows local fault handlers to be static. Signed-off-by: Andrew Cooper --- arch/x86/include/arch/extable.h | 8 ++++---- arch/x86/include/arch/lib.h | 9 +++++---- tests/cpuid-faulting/main.c | 8 ++++---- tests/fpu-exception-emulation/main.c | 20 ++++++++++++-------- tests/xsa-173/main.c | 7 ++++--- tests/xsa-186/main.c | 7 ++++--- tests/xsa-191/main.c | 10 ++++++---- tests/xsa-192/main.c | 5 +++-- tests/xsa-196/main.c | 5 +++-- tests/xsa-200/main.c | 4 ++-- 10 files changed, 47 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/arch/extable.h b/arch/x86/include/arch/extable.h index 3039d16..792f26c 100644 --- a/arch/x86/include/arch/extable.h +++ b/arch/x86/include/arch/extable.h @@ -15,8 +15,8 @@ * Sample usage: *
  *   asm volatile ("1: $INSN; 2:"
- *                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
- *                 : "=a" (fault) : "0" (0));
+ *                 _ASM_EXTABLE_HANDLER(1b, 2b, @%c[ex])
+ *                 : "=a" (fault) : "0" (0), [ex] "i" (ex_record_fault_eax));
  * 
*/ bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex); @@ -27,8 +27,8 @@ bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex); * Sample usage: *
  *   asm volatile ("1: $INSN; 2:"
- *                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
- *                 : "=D" (fault) : "0" (0));
+ *                 _ASM_EXTABLE_HANDLER(1b, 2b, @%c[ex])
+ *                 : "=D" (fault) : "0" (0), [ex] "i" (ex_record_fault_edi));
  * 
*/ bool ex_record_fault_edi(struct cpu_regs *regs, const struct extable_entry *ex); diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h index 405343c..961274a 100644 --- a/arch/x86/include/arch/lib.h +++ b/arch/x86/include/arch/lib.h @@ -19,9 +19,9 @@ static inline bool rdmsr_safe(uint32_t idx, uint64_t *val) uint32_t lo, hi, new_idx; asm volatile("1: rdmsr; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_rdmsr_safe) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=a" (lo), "=d" (hi), "=c" (new_idx) - : "c" (idx)); + : "c" (idx), [ex] "i" (ex_rdmsr_safe)); bool fault = idx != new_idx; @@ -43,10 +43,11 @@ static inline bool wrmsr_safe(uint32_t idx, uint64_t val) uint32_t new_idx; asm volatile ("1: wrmsr; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_wrmsr_safe) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=c" (new_idx) : "c" (idx), "a" ((uint32_t)val), - "d" ((uint32_t)(val >> 32))); + "d" ((uint32_t)(val >> 32)), + [ex] "i" (ex_wrmsr_safe)); return idx != new_idx; } diff --git a/tests/cpuid-faulting/main.c b/tests/cpuid-faulting/main.c index 2726576..cc1baa3 100644 --- a/tests/cpuid-faulting/main.c +++ b/tests/cpuid-faulting/main.c @@ -34,9 +34,9 @@ unsigned long stub_cpuid(void) unsigned int fault = 0, tmp; asm volatile("1: cpuid; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=a" (tmp), "+D" (fault) - : "a" (0) + : "a" (0), [ex] "i" (ex_record_fault_edi) : "ebx", "ecx", "edx"); return fault; @@ -48,9 +48,9 @@ unsigned long stub_fep_cpuid(void) asm volatile(_ASM_XEN_FEP "1: cpuid; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=a" (tmp), "+D" (fault) - : "a" (0) + : "a" (0), [ex] "i" (ex_record_fault_edi) : "ebx", "ecx", "edx"); return fault; diff --git a/tests/fpu-exception-emulation/main.c b/tests/fpu-exception-emulation/main.c index b30b1b3..24ec1df 100644 --- a/tests/fpu-exception-emulation/main.c +++ b/tests/fpu-exception-emulation/main.c @@ -77,9 +77,10 @@ exinfo_t probe_x87(bool force) "jz 1f;" _ASM_XEN_FEP "1: fnop; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "+a" (fault) - : [fep] "q" (force)); + : [fep] "q" (force), + [ex] "i" (ex_record_fault_eax)); return fault; } @@ -109,9 +110,10 @@ exinfo_t probe_x87_wait(bool force) "jz 1f;" _ASM_XEN_FEP "1: wait; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "+a" (fault) - : [fep] "q" (force)); + : [fep] "q" (force), + [ex] "i" (ex_record_fault_eax)); return fault; } @@ -140,9 +142,10 @@ exinfo_t probe_mmx(bool force) "jz 1f;" _ASM_XEN_FEP "1: movq %%mm0, %%mm0; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "+a" (fault) - : [fep] "q" (force)); + : [fep] "q" (force), + [ex] "i" (ex_record_fault_eax)); return fault; } @@ -155,9 +158,10 @@ exinfo_t probe_sse(bool force) "jz 1f;" _ASM_XEN_FEP "1: movups %%xmm0, %%xmm0; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "+a" (fault) - : [fep] "q" (force)); + : [fep] "q" (force), + [ex] "i" (ex_record_fault_eax)); return fault; } diff --git a/tests/xsa-173/main.c b/tests/xsa-173/main.c index e0f10f5..a4bc6de 100644 --- a/tests/xsa-173/main.c +++ b/tests/xsa-173/main.c @@ -33,7 +33,7 @@ uint64_t nl2[PAE_L2_PT_ENTRIES] __aligned(PAGE_SIZE); static bool seen_fault; -bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex) +static bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex) { /* Expect to see #PF indicating that a reserved bits was set. */ if ( regs->entry_vector == X86_EXC_PF && @@ -66,9 +66,10 @@ void test_main(void) ptr = _p((4ULL << PAE_L3_PT_SHIFT) + MB(1)); asm volatile ("1:mov (%[ptr]), %[val]; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_fault) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : [val] "=q" (val) - : [ptr] "r" (ptr) + : [ptr] "r" (ptr), + [ex] "i" (ex_fault) : "memory"); if ( seen_fault ) diff --git a/tests/xsa-186/main.c b/tests/xsa-186/main.c index 1d6367d..869c9d5 100644 --- a/tests/xsa-186/main.c +++ b/tests/xsa-186/main.c @@ -61,7 +61,7 @@ asm(".align 16;" "insn_stub_end:;" ); -bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex) +static bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex) { if ( regs->entry_vector == X86_EXC_GP && regs->error_code == 0 ) { @@ -178,10 +178,11 @@ void test_main(void) * instructions don't get lost. */ asm volatile ("call *%[ptr];" - _ASM_EXTABLE_HANDLER(-1, 0, ex_fault) + _ASM_EXTABLE_HANDLER(-1, 0, %c[ex]) : "=a" (res) : "0" (0), - [ptr] "r" (stub) + [ptr] "r" (stub), + [ex] "i" (ex_fault) : "memory"); if ( res != 0xc0de ) diff --git a/tests/xsa-191/main.c b/tests/xsa-191/main.c index 7bc29a7..d78c95c 100644 --- a/tests/xsa-191/main.c +++ b/tests/xsa-191/main.c @@ -44,10 +44,11 @@ void test_main(void) write_fs(0); asm volatile (_ASM_XEN_FEP "1: mov %%fs:0, %[dst]; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=D" (fault), [dst] "=r" (tmp) - : "D" (0)); + : "D" (0), + [ex] "i" (ex_record_fault_edi)); switch ( fault ) { @@ -82,10 +83,11 @@ void test_main(void) asm volatile (_ASM_XEN_FEP "1: mov %[sel], %%fs; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=a" (fault) : "a" (0), - [sel] "r" (4)); + [sel] "r" (4), + [ex] "i" (ex_record_fault_eax)); switch ( fault ) { diff --git a/tests/xsa-192/main.c b/tests/xsa-192/main.c index c930e9d..8d72cb7 100644 --- a/tests/xsa-192/main.c +++ b/tests/xsa-192/main.c @@ -69,9 +69,10 @@ unsigned long user_ldt_use(void) /* Attempt to load %fs from the LDT. */ asm volatile ("1: mov %[sel], %%fs; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "+a" (fault) - : [sel] "r" (LDT_SEL)); + : [sel] "r" (LDT_SEL), + [ex] "i" (ex_record_fault_eax)); return fault; } diff --git a/tests/xsa-196/main.c b/tests/xsa-196/main.c index 4a0ec12..3f03092 100644 --- a/tests/xsa-196/main.c +++ b/tests/xsa-196/main.c @@ -56,7 +56,7 @@ unsigned long compat_userspace(void) "start_32bit:;" _ASM_XEN_FEP "1: int $%c[df]; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) /* Return to 64bit. */ "ljmpl $%c[cs], $1f;" @@ -66,7 +66,8 @@ unsigned long compat_userspace(void) : "+a" (fault) : [df] "i" (X86_EXC_DF), [cs32] "i" (GDTE_CS32_DPL3 * 8 + 3), - [cs] "i" (__USER_CS)); + [cs] "i" (__USER_CS), + [ex] "i" (ex_record_fault_eax)); return fault; } diff --git a/tests/xsa-200/main.c b/tests/xsa-200/main.c index fd30c4d..69b1d3c 100644 --- a/tests/xsa-200/main.c +++ b/tests/xsa-200/main.c @@ -45,10 +45,10 @@ void test_main(void) { /* Poke the emulator. */ asm volatile (_ASM_XEN_FEP "1: .byte 0x66; cmpxchg8b %[ptr]; 2:" - _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi) + _ASM_EXTABLE_HANDLER(1b, 2b, %c[ex]) : "=A" (prev), [ptr] "+m" (mem), "+D" (fault) : "c" ((uint32_t)(new >> 32)), "b" ((uint32_t)new), - "0" (old)); + "0" (old), [ex] "i" (ex_record_fault_edi)); if ( fault == EXINFO_SYM(UD, 0) ) return xtf_success("Success: Not vulnerable to XSA-200\n"); -- 2.39.5