From a792ac6a4827cb7210f369041908bba0a09ff1a2 Mon Sep 17 00:00:00 2001 From: losfair Date: Wed, 26 Jun 2019 20:44:51 +0800 Subject: [PATCH] Wrap alternative stack functions properly. --- lib/runtime-core/image-loading-linux-x86-64.s | 8 +- lib/runtime-core/image-loading-macos-x86-64.s | 8 +- lib/runtime-core/src/alternative_stack.rs | 48 ++++++++++ lib/runtime-core/src/lib.rs | 2 + lib/runtime-core/src/state.rs | 6 +- lib/singlepass-backend/src/protect_unix.rs | 91 ++++++++++--------- 6 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 lib/runtime-core/src/alternative_stack.rs diff --git a/lib/runtime-core/image-loading-linux-x86-64.s b/lib/runtime-core/image-loading-linux-x86-64.s index b43c0f78c..e9893968c 100644 --- a/lib/runtime-core/image-loading-linux-x86-64.s +++ b/lib/runtime-core/image-loading-linux-x86-64.s @@ -1,5 +1,5 @@ -.globl run_on_wasm_stack -run_on_wasm_stack: +.globl run_on_alternative_stack +run_on_alternative_stack: # (stack_end, stack_begin) # We need to ensure 16-byte alignment here. pushq %r15 @@ -10,7 +10,7 @@ pushq %rbx pushq %rbp movq %rsp, -16(%rdi) -leaq run_on_wasm_stack.returning(%rip), %rax +leaq run_on_alternative_stack.returning(%rip), %rax movq %rax, -24(%rdi) movq %rsi, %rsp @@ -22,7 +22,7 @@ popq %r14 popq %r15 retq -run_on_wasm_stack.returning: +run_on_alternative_stack.returning: movq (%rsp), %rsp popq %rbp popq %rbx diff --git a/lib/runtime-core/image-loading-macos-x86-64.s b/lib/runtime-core/image-loading-macos-x86-64.s index 122c16505..d2f5f761c 100644 --- a/lib/runtime-core/image-loading-macos-x86-64.s +++ b/lib/runtime-core/image-loading-macos-x86-64.s @@ -1,5 +1,5 @@ -.globl _run_on_wasm_stack -_run_on_wasm_stack: +.globl _run_on_alternative_stack +_run_on_alternative_stack: # (stack_end, stack_begin) # We need to ensure 16-byte alignment here. pushq %r15 @@ -10,7 +10,7 @@ pushq %rbx pushq %rbp movq %rsp, -16(%rdi) -leaq _run_on_wasm_stack.returning(%rip), %rax +leaq _run_on_alternative_stack.returning(%rip), %rax movq %rax, -24(%rdi) movq %rsi, %rsp @@ -22,7 +22,7 @@ popq %r14 popq %r15 retq -_run_on_wasm_stack.returning: +_run_on_alternative_stack.returning: movq (%rsp), %rsp popq %rbp popq %rbx diff --git a/lib/runtime-core/src/alternative_stack.rs b/lib/runtime-core/src/alternative_stack.rs new file mode 100644 index 000000000..8b06b0176 --- /dev/null +++ b/lib/runtime-core/src/alternative_stack.rs @@ -0,0 +1,48 @@ +mod raw { + extern "C" { + pub fn run_on_alternative_stack( + stack_end: *mut u64, + stack_begin: *mut u64, + userdata_arg2: *mut u8, + ) -> u64; + } +} + +pub(crate) unsafe fn run_on_alternative_stack(stack_end: *mut u64, stack_begin: *mut u64) -> u64 { + raw::run_on_alternative_stack(stack_end, stack_begin, ::std::ptr::null_mut()) +} + +pub fn allocate_and_run R>(size: usize, f: F) -> R { + struct Context R, R> { + f: Option, + ret: Option, + } + + extern "C" fn invoke R, R>(_: u64, _: u64, ctx: &mut Context) { + let f = ctx.f.take().unwrap(); + ctx.ret = Some(f()); + } + + unsafe { + let mut ctx = Context { + f: Some(f), + ret: None, + }; + assert!(size % 16 == 0); + assert!(size >= 4096); + + let mut stack: Vec = vec![0; size / 8]; + let mut end_offset = stack.len(); + + stack[end_offset - 4] = invoke:: as usize as u64; + let stack_begin = stack.as_mut_ptr().offset((end_offset - 4 - 6) as isize); + let stack_end = stack.as_mut_ptr().offset(end_offset as isize); + + raw::run_on_alternative_stack( + stack_end, + stack_begin, + &mut ctx as *mut Context as *mut u8, + ); + ctx.ret.take().unwrap() + } +} diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 3675fcc63..8b7a29156 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -43,6 +43,8 @@ pub mod vm; pub mod vmcalls; #[cfg(all(unix, target_arch = "x86_64"))] pub use trampoline_x64 as trampoline; +#[cfg(all(unix, target_arch = "x86_64"))] +pub mod alternative_stack; pub mod state; #[cfg(all(unix, target_arch = "x86_64"))] pub mod suspend; diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 210697444..9b697d083 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -321,10 +321,8 @@ impl ExecutionStateImage { #[cfg(all(unix, target_arch = "x86_64"))] pub mod x64 { - extern "C" { - fn run_on_wasm_stack(stack_end: *mut u64, stack_begin: *mut u64) -> u64; - } use super::*; + use crate::alternative_stack::run_on_alternative_stack; use crate::structures::TypedIndex; use crate::types::LocalGlobalIndex; use crate::vm::Ctx; @@ -515,7 +513,7 @@ pub mod x64 { image.globals[i]; } - run_on_wasm_stack( + run_on_alternative_stack( stack.as_mut_ptr().offset(stack.len() as isize), stack.as_mut_ptr().offset(stack_offset as isize), ) diff --git a/lib/singlepass-backend/src/protect_unix.rs b/lib/singlepass-backend/src/protect_unix.rs index b93c881fd..f17823eac 100644 --- a/lib/singlepass-backend/src/protect_unix.rs +++ b/lib/singlepass-backend/src/protect_unix.rs @@ -20,6 +20,7 @@ use std::collections::HashMap; use std::ptr; use std::sync::Arc; use std::sync::Once; +use wasmer_runtime_core::alternative_stack::allocate_and_run; use wasmer_runtime_core::codegen::BkptInfo; use wasmer_runtime_core::state::x64::{read_stack, X64Register, GPR}; use wasmer_runtime_core::typed_func::WasmTrapInfo; @@ -46,32 +47,35 @@ extern "C" fn signal_trap_handler( _ => {} } - // TODO: make this safer - let ctx = &*(fault.known_registers[X64Register::GPR(GPR::R15).to_index().0].unwrap() - as *mut vm::Ctx); - let rsp = fault.known_registers[X64Register::GPR(GPR::RSP).to_index().0].unwrap(); + allocate_and_run(65536, || { + // TODO: make this safer + let ctx = &*(fault.known_registers[X64Register::GPR(GPR::R15).to_index().0].unwrap() + as *mut vm::Ctx); + let rsp = fault.known_registers[X64Register::GPR(GPR::RSP).to_index().0].unwrap(); - let msm = (*ctx.module) - .runnable_module - .get_module_state_map() - .unwrap(); - let code_base = (*ctx.module).runnable_module.get_code().unwrap().as_ptr() as usize; - let image = self::read_stack( - &msm, - code_base, - rsp as usize as *const u64, - fault.known_registers, - Some(fault.ip as usize as u64), - ); + let msm = (*ctx.module) + .runnable_module + .get_module_state_map() + .unwrap(); + let code_base = (*ctx.module).runnable_module.get_code().unwrap().as_ptr() as usize; + let image = self::read_stack( + &msm, + code_base, + rsp as usize as *const u64, + fault.known_registers, + Some(fault.ip as usize as u64), + ); + + use colored::*; + eprintln!( + "\n{}", + "Wasmer encountered an error while running your WebAssembly program." + .bold() + .red() + ); + image.print_backtrace_if_needed(); + }); - use colored::*; - eprintln!( - "\n{}", - "Wasmer encountered an error while running your WebAssembly program." - .bold() - .red() - ); - image.print_backtrace_if_needed(); do_unwind(signum, siginfo as _, ucontext); } } @@ -191,8 +195,8 @@ pub struct FaultInfo { #[cfg(all(target_os = "linux", target_arch = "x86_64"))] unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *const c_void) -> FaultInfo { use libc::{ - ucontext_t, R10, R11, R12, R13, R14, R15, R8, R9, RAX, RBP, RBX, RCX, RDI, RDX, RIP, RSI, - RSP, + ucontext_t, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9, REG_RAX, + REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP, }; #[allow(dead_code)] @@ -212,30 +216,29 @@ unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *const c_void) -> Fau let gregs = &(*ucontext).uc_mcontext.gregs; let mut known_registers: [Option; 24] = [None; 24]; + known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs[REG_R15 as usize] as _); + known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs[REG_R14 as usize] as _); + known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs[REG_R13 as usize] as _); + known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs[REG_R12 as usize] as _); + known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs[REG_R11 as usize] as _); + known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs[REG_R10 as usize] as _); + known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs[REG_R9 as usize] as _); + known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs[REG_R8 as usize] as _); + known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs[REG_RSI as usize] as _); + known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs[REG_RDI as usize] as _); + known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs[REG_RDX as usize] as _); + known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs[REG_RCX as usize] as _); + known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs[REG_RBX as usize] as _); + known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs[REG_RAX as usize] as _); - known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs[R15 as usize] as _); - known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs[R14 as usize] as _); - known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs[R13 as usize] as _); - known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs[R12 as usize] as _); - known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs[R11 as usize] as _); - known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs[R10 as usize] as _); - known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs[R9 as usize] as _); - known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs[R8 as usize] as _); - known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs[RSI as usize] as _); - known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs[RDI as usize] as _); - known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs[RDX as usize] as _); - known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs[RCX as usize] as _); - known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs[RBX as usize] as _); - known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs[RAX as usize] as _); - - known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs[RBP as usize] as _); - known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs[RSP as usize] as _); + known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs[REG_RBP as usize] as _); + known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs[REG_RSP as usize] as _); // TODO: XMM registers FaultInfo { faulting_addr: si_addr as usize as _, - ip: gregs[RIP as usize] as _, + ip: gregs[REG_RIP as usize] as _, known_registers, } }