From db93d2693d4d866a7183addd01bf4f975a2e62c5 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 18 Dec 2018 23:21:18 -0800 Subject: [PATCH] Make setjmp/longjmp more secure --- src/apis/emscripten/jmp.rs | 19 +++++++++++++++---- src/webassembly/instance.rs | 4 ++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/apis/emscripten/jmp.rs b/src/apis/emscripten/jmp.rs index f22624cc8..49ec783ba 100644 --- a/src/apis/emscripten/jmp.rs +++ b/src/apis/emscripten/jmp.rs @@ -1,12 +1,21 @@ use crate::webassembly::Instance; use libc::{c_int, c_void}; +use std::cell::UnsafeCell; /// setjmp pub extern "C" fn __setjmp(env_addr: u32, instance: &mut Instance) -> c_int { debug!("emscripten::__setjmp (setjmp)"); unsafe { - let env = instance.memory_offset_addr(0, env_addr as usize) as *mut c_void; - setjmp(env) + // Rather than using the env as the holder of the jump address, + // we obscure that id so we are in complete control of it + let obscure_env = instance.memory_offset_addr(0, env_addr as usize) as *mut i8; + let jmp_buf: UnsafeCell<[c_int; 27]> = UnsafeCell::new([0; 27]); + let mut jumps = &mut instance.emscripten_data.as_mut().unwrap().jumps; + let result = setjmp(jmp_buf.get() as _); + *obscure_env = jumps.len() as _; + jumps.push(jmp_buf); + // We use the index of the jump as the jump buffer (env) + result } } @@ -14,8 +23,10 @@ pub extern "C" fn __setjmp(env_addr: u32, instance: &mut Instance) -> c_int { pub extern "C" fn __longjmp(env_addr: u32, val: c_int, instance: &mut Instance) -> ! { debug!("emscripten::__longjmp (longjmp) {}", val); unsafe { - let env = instance.memory_offset_addr(0, env_addr as usize) as *mut c_void; - longjmp(env, val) + let obscure_env = instance.memory_offset_addr(0, env_addr as usize) as *mut i8; + let mut jumps = &mut instance.emscripten_data.as_mut().unwrap().jumps; + let mut real_env = &jumps[*obscure_env as usize]; + longjmp(real_env.get() as _, val) }; } diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index a958f27c2..1692e9cd0 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -15,7 +15,9 @@ use cranelift_wasm::{FuncIndex, GlobalInit}; use indicatif::{ProgressBar, ProgressStyle}; use rayon::prelude::*; +use libc::c_int; use region; +use std::cell::UnsafeCell; use std::iter::FromIterator; use std::iter::Iterator; use std::mem::size_of; @@ -72,6 +74,7 @@ pub struct EmscriptenData { pub memalign: extern "C" fn(u32, u32, &mut Instance) -> u32, pub memset: extern "C" fn(u32, i32, u32, &mut Instance) -> u32, pub stack_alloc: extern "C" fn(u32, &Instance) -> u32, + pub jumps: Vec>, } impl EmscriptenData { @@ -116,6 +119,7 @@ impl EmscriptenData { memalign: mem::transmute(memalign_addr), memset: mem::transmute(memset_addr), stack_alloc: mem::transmute(stack_alloc_addr), + jumps: Vec::new(), } } }