@@ -36,15 +36,17 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector,
uint64_t arg4, bool *raised_vector)
{
extern char ret_to_kernel[];
- uint64_t rax = 0;
+ volatile uint64_t rax = 0;
static unsigned char user_stack[USERMODE_STACK_SIZE];
+ handler old_ex;
*raised_vector = 0;
set_idt_entry(RET_TO_KERNEL_IRQ, ret_to_kernel, 3);
- handle_exception(fault_vector,
- restore_exec_to_jmpbuf_exception_handler);
+ old_ex = handle_exception(fault_vector,
+ restore_exec_to_jmpbuf_exception_handler);
if (setjmp(jmpbuf) != 0) {
+ handle_exception(fault_vector, old_ex);
*raised_vector = 1;
return 0;
}
@@ -114,5 +116,7 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector,
:
"rsi", "rdi", "rcx", "rdx");
+ handle_exception(fault_vector, old_ex);
+
return rax;
}
run_in_user() replaces the exception handler for the expected fault vector to ensure the code can properly return back to kernel mode in case of such exceptions. However, it leaves the exception handler in place which may confuse later test code triggering the same exception without installing a handler first. Fix this be restoring the previous exception handler. Running the longjmp() handler out of context will lead to no good. We now also need to make 'rax' volatile to avoid a related compiler warning. Signed-off-by: Mathias Krause <minipli@grsecurity.net> --- lib/x86/usermode.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)