From de21d6fd9f3a67168438c42d6f1413e7c7d637d2 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 24 Dec 2015 23:22:48 +0000 Subject: [PATCH] Allow a test to raise privilege back to kernel level to facilitate tests which switches privilege during the course of its run. This is achieved by providing a dpl3 IDT entry which restores %esp and jumps to the %eip found in the exception frame. Therefore, 'int $0x20' acts as function call which returns at the kernels cpl. Signed-off-by: Andrew Cooper --- arch/x86/entry_32.S | 9 +++++++++ arch/x86/entry_64.S | 8 ++++++++ arch/x86/hvm/traps.c | 3 +++ arch/x86/pv/traps.c | 4 ++++ 4 files changed, 24 insertions(+) diff --git a/arch/x86/entry_32.S b/arch/x86/entry_32.S index a22bce2..bda1150 100644 --- a/arch/x86/entry_32.S +++ b/arch/x86/entry_32.S @@ -80,3 +80,12 @@ handle_exception: add $8, %esp /* Pop error_code/entry_vector. */ env_IRET + + +ENTRY(entry_ret_to_kernel) /* int $0x20 (return to kernel) */ + + /* User required to ensure this is called from CPL > KERNEL_RPL */ + + mov 0*4(%esp), %eax /* Stash %eip from iret frame */ + mov 3*4(%esp), %esp /* Load %esp from iret frame */ + jmp *%eax /* Jump back */ diff --git a/arch/x86/entry_64.S b/arch/x86/entry_64.S index a0fb058..e1b5baa 100644 --- a/arch/x86/entry_64.S +++ b/arch/x86/entry_64.S @@ -94,3 +94,11 @@ handle_exception: add $8, %rsp /* Pop error_code/entry_vector. */ env_IRETQ + + +ENTRY(entry_ret_to_kernel) /* int $0x20 (return to kernel) */ + env_ADJUST_FRAME + + mov 0*8(%rsp), %rax /* Stash %rip from iret frame */ + mov 3*8(%rsp), %rsp /* Load %esp from iret frame */ + jmp *%rax /* Jump back */ diff --git a/arch/x86/hvm/traps.c b/arch/x86/hvm/traps.c index 5f478bc..a860153 100644 --- a/arch/x86/hvm/traps.c +++ b/arch/x86/hvm/traps.c @@ -24,6 +24,7 @@ void entry_AC(void); void entry_MC(void); void entry_XM(void); void entry_VE(void); +void entry_ret_to_kernel(void); hw_tss tss __aligned(16) = { @@ -101,6 +102,8 @@ void arch_init_traps(void) setup_gate(X86_EXC_XM, &entry_XM, 0); setup_gate(X86_EXC_VE, &entry_VE, 0); + setup_gate(0x20, &entry_ret_to_kernel, 3); + asm volatile ("lidt idt_ptr"); gdt[GDTE_TSS] = (typeof(*gdt))INIT_GDTE_RAW((unsigned long)&tss, 0x67, 0x89); diff --git a/arch/x86/pv/traps.c b/arch/x86/pv/traps.c index 208adcf..51c2ec9 100644 --- a/arch/x86/pv/traps.c +++ b/arch/x86/pv/traps.c @@ -26,6 +26,7 @@ void entry_AC(void); void entry_MC(void); void entry_XM(void); void entry_VE(void); +void entry_ret_to_kernel(void); struct xen_trap_info pv_default_trap_info[] = { @@ -48,6 +49,9 @@ struct xen_trap_info pv_default_trap_info[] = { X86_EXC_MC, 0|4, __KERN_CS, (unsigned long)&entry_MC }, { X86_EXC_XM, 0|4, __KERN_CS, (unsigned long)&entry_XM }, { X86_EXC_VE, 0|4, __KERN_CS, (unsigned long)&entry_VE }, + + { 0x20, 3|4, __KERN_CS, (unsigned long)&entry_ret_to_kernel }, + { 0 }, /* Sentinel. */ }; -- 2.39.5