Enforce runtime memory and stack bound check when using kernel loader.

This commit is contained in:
Heyang Zhou
2019-05-06 07:15:30 -07:00
parent 7bc09ee220
commit 61510f8116
9 changed files with 121 additions and 25 deletions

6
Cargo.lock generated
View File

@ -530,7 +530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "dynasm" name = "dynasm"
version = "0.3.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2399,7 +2399,7 @@ name = "wasmer-singlepass-backend"
version = "0.3.0" version = "0.3.0"
dependencies = [ dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dynasm 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "dynasm 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2645,7 +2645,7 @@ dependencies = [
"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
"checksum dynasm 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b77e128faecc4d16cff7cae96c0c9e809f687f748a0dbc4d017996e48240a991" "checksum dynasm 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f36d49ab6f8ecc642d2c6ee10fda04ba68003ef0277300866745cdde160e6b40"
"checksum dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c408a211e7f5762829f5e46bdff0c14bc3b1517a21a4bb781c716bf88b0c68" "checksum dynasmrt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c408a211e7f5762829f5e46bdff0c14bc3b1517a21a4bb781c716bf88b0c68"
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"

View File

@ -40,15 +40,12 @@ impl Token {
} }
/// Configuration data for the compiler /// Configuration data for the compiler
#[derive(Default)]
pub struct CompilerConfig { pub struct CompilerConfig {
/// Symbol information generated from emscripten; used for more detailed debug messages /// Symbol information generated from emscripten; used for more detailed debug messages
pub symbol_map: Option<HashMap<u32, String>>, pub symbol_map: Option<HashMap<u32, String>>,
} pub enforce_memory_bound_check: bool,
pub enforce_stack_check: bool,
impl Default for CompilerConfig {
fn default() -> CompilerConfig {
CompilerConfig { symbol_map: None }
}
} }
pub trait Compiler { pub trait Compiler {

View File

@ -43,6 +43,8 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
/// Adds an import function. /// Adds an import function.
fn feed_import_function(&mut self) -> Result<(), E>; fn feed_import_function(&mut self) -> Result<(), E>;
fn feed_compiler_config(&mut self, config: &CompilerConfig) -> Result<(), E> { Ok(()) }
} }
pub struct StreamingCompiler< pub struct StreamingCompiler<

View File

@ -53,6 +53,8 @@ pub fn read_module<
middlewares: &mut MiddlewareChain, middlewares: &mut MiddlewareChain,
compiler_config: &CompilerConfig, compiler_config: &CompilerConfig,
) -> Result<ModuleInfo, LoadError> { ) -> Result<ModuleInfo, LoadError> {
mcg.feed_compiler_config(compiler_config)
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
let mut info = ModuleInfo { let mut info = ModuleInfo {
memories: Map::new(), memories: Map::new(),
globals: Map::new(), globals: Map::new(),

View File

@ -65,6 +65,8 @@ pub struct InternalCtx {
pub dynamic_sigindices: *const SigId, pub dynamic_sigindices: *const SigId,
pub intrinsics: *const Intrinsics, pub intrinsics: *const Intrinsics,
pub stack_lower_bound: *mut u8,
} }
#[repr(C)] #[repr(C)]
@ -157,6 +159,8 @@ impl Ctx {
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info), intrinsics: get_intrinsics_for_module(&module.info),
stack_lower_bound: ::std::ptr::null_mut(),
}, },
local_functions: local_backing.local_functions.as_ptr(), local_functions: local_backing.local_functions.as_ptr(),
@ -191,6 +195,8 @@ impl Ctx {
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info), intrinsics: get_intrinsics_for_module(&module.info),
stack_lower_bound: ::std::ptr::null_mut(),
}, },
local_functions: local_backing.local_functions.as_ptr(), local_functions: local_backing.local_functions.as_ptr(),
@ -288,9 +294,13 @@ impl Ctx {
8 * (mem::size_of::<usize>() as u8) 8 * (mem::size_of::<usize>() as u8)
} }
pub fn offset_local_functions() -> u8 { pub fn offset_stack_lower_bound() -> u8 {
9 * (mem::size_of::<usize>() as u8) 9 * (mem::size_of::<usize>() as u8)
} }
pub fn offset_local_functions() -> u8 {
10 * (mem::size_of::<usize>() as u8)
}
} }
enum InnerFunc {} enum InnerFunc {}
@ -489,6 +499,11 @@ mod vm_offset_tests {
offset_of!(InternalCtx => intrinsics).get_byte_offset(), offset_of!(InternalCtx => intrinsics).get_byte_offset(),
); );
assert_eq!(
Ctx::offset_stack_lower_bound() as usize,
offset_of!(InternalCtx => stack_lower_bound).get_byte_offset(),
);
assert_eq!( assert_eq!(
Ctx::offset_local_functions() as usize, Ctx::offset_local_functions() as usize,
offset_of!(Ctx => local_functions).get_byte_offset(), offset_of!(Ctx => local_functions).get_byte_offset(),

View File

@ -10,7 +10,7 @@ edition = "2018"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
wasmparser = "0.29.2" wasmparser = "0.29.2"
dynasm = "0.3.1" dynasm = "0.3.2"
dynasmrt = "0.3.1" dynasmrt = "0.3.1"
lazy_static = "1.2.0" lazy_static = "1.2.0"
byteorder = "1" byteorder = "1"

View File

@ -10,7 +10,7 @@ use smallvec::SmallVec;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::{any::Any, collections::HashMap, sync::Arc}; use std::{any::Any, collections::HashMap, sync::Arc};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::{Backend, RunnableModule}, backend::{Backend, RunnableModule, CompilerConfig},
codegen::*, codegen::*,
memory::MemoryType, memory::MemoryType,
module::ModuleInfo, module::ModuleInfo,
@ -120,6 +120,8 @@ pub struct X64ModuleCodeGenerator {
function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>, function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>,
assembler: Option<Assembler>, assembler: Option<Assembler>,
func_import_count: usize, func_import_count: usize,
config: Option<Arc<CodegenConfig>>,
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -143,6 +145,8 @@ pub struct X64FunctionCode {
control_stack: Vec<ControlFrame>, control_stack: Vec<ControlFrame>,
machine: Machine, machine: Machine,
unreachable_depth: usize, unreachable_depth: usize,
config: Arc<CodegenConfig>,
} }
enum FuncPtrInner {} enum FuncPtrInner {}
@ -284,6 +288,12 @@ pub struct CodegenError {
pub message: &'static str, pub message: &'static str,
} }
#[derive(Copy, Clone, Debug)]
struct CodegenConfig {
enforce_memory_bound_check: bool,
enforce_stack_check: bool,
}
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
for X64ModuleCodeGenerator for X64ModuleCodeGenerator
{ {
@ -295,6 +305,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
function_labels: Some(HashMap::new()), function_labels: Some(HashMap::new()),
assembler: Some(Assembler::new().unwrap()), assembler: Some(Assembler::new().unwrap()),
func_import_count: 0, func_import_count: 0,
config: None,
} }
} }
@ -348,6 +359,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
control_stack: vec![], control_stack: vec![],
machine: Machine::new(), machine: Machine::new(),
unreachable_depth: 0, unreachable_depth: 0,
config: self.config.as_ref().unwrap().clone(),
}; };
self.functions.push(code); self.functions.push(code);
Ok(self.functions.last_mut().unwrap()) Ok(self.functions.last_mut().unwrap())
@ -460,6 +472,14 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
Ok(()) Ok(())
} }
fn feed_compiler_config(&mut self, config: &CompilerConfig) -> Result<(), CodegenError> {
self.config = Some(Arc::new(CodegenConfig {
enforce_memory_bound_check: config.enforce_memory_bound_check,
enforce_stack_check: config.enforce_stack_check,
}));
Ok(())
}
} }
impl X64FunctionCode { impl X64FunctionCode {
@ -1173,6 +1193,7 @@ impl X64FunctionCode {
/// Emits a memory operation. /// Emits a memory operation.
fn emit_memory_op<F: FnOnce(&mut Assembler, &mut Machine, GPR)>( fn emit_memory_op<F: FnOnce(&mut Assembler, &mut Machine, GPR)>(
module_info: &ModuleInfo, module_info: &ModuleInfo,
config: &CodegenConfig,
a: &mut Assembler, a: &mut Assembler,
m: &mut Machine, m: &mut Machine,
addr: Location, addr: Location,
@ -1222,9 +1243,13 @@ impl X64FunctionCode {
&module_info.imported_memories[import_mem_index].1 &module_info.imported_memories[import_mem_index].1
} }
}; };
let need_check = match mem_desc.memory_type() { let need_check = if config.enforce_memory_bound_check {
MemoryType::Dynamic => true, true
MemoryType::Static | MemoryType::SharedStatic => false, } else {
match mem_desc.memory_type() {
MemoryType::Dynamic => true,
MemoryType::Static | MemoryType::SharedStatic => false,
}
}; };
if need_check { if need_check {
@ -1391,6 +1416,19 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
a.emit_push(Size::S64, Location::GPR(GPR::RBP)); a.emit_push(Size::S64, Location::GPR(GPR::RBP));
a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RBP)); a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RBP));
// Stack check.
if self.config.enforce_stack_check {
a.emit_cmp(
Size::S64,
Location::Memory(
GPR::RDI, // first parameter is vmctx
vm::Ctx::offset_stack_lower_bound() as i32,
),
Location::GPR(GPR::RSP)
);
a.emit_conditional_trap(Condition::Below);
}
self.locals = self self.locals = self
.machine .machine
.init_locals(a, self.num_locals, self.num_params); .init_locals(a, self.num_locals, self.num_params);
@ -3351,6 +3389,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3376,6 +3415,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3401,6 +3441,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3427,6 +3468,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3453,6 +3495,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3479,6 +3522,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3505,6 +3549,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3530,6 +3575,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3555,6 +3601,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3580,6 +3627,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3605,6 +3653,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3630,6 +3679,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3655,6 +3705,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3681,6 +3732,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3707,6 +3759,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3733,6 +3786,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3759,6 +3813,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3790,6 +3845,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target, target,
@ -3816,6 +3872,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3841,6 +3898,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3866,6 +3924,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3891,6 +3950,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,
@ -3916,6 +3976,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Self::emit_memory_op( Self::emit_memory_op(
module_info, module_info,
&self.config,
a, a,
&mut self.machine, &mut self.machine,
target_addr, target_addr,

View File

@ -50,6 +50,8 @@ fn handle_client(mut stream: UnixStream) {
&wasm_binary[..], &wasm_binary[..],
CompilerConfig { CompilerConfig {
symbol_map: None, symbol_map: None,
enforce_memory_bound_check: true,
enforce_stack_check: true,
}, },
&SinglePassCompiler::new(), &SinglePassCompiler::new(),
).unwrap(); ).unwrap();

View File

@ -287,7 +287,32 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
Backend::LLVM => return Err("the llvm backend is not enabled".to_string()), Backend::LLVM => return Err("the llvm backend is not enabled".to_string()),
}; };
let module = if !disable_cache { let is_kernel_loader = if let Some(LoaderName::Kernel) = options.loader {
true
} else {
false
};
let module = if is_kernel_loader {
webassembly::compile_with_config_with(
&wasm_binary[..],
CompilerConfig {
symbol_map: em_symbol_map,
enforce_memory_bound_check: true,
enforce_stack_check: true,
},
&*compiler,
).map_err(|e| format!("Can't compile module: {:?}", e))?
} else if disable_cache {
webassembly::compile_with_config_with(
&wasm_binary[..],
CompilerConfig {
symbol_map: em_symbol_map,
..Default::default()
},
&*compiler,
).map_err(|e| format!("Can't compile module: {:?}", e))?
} else {
// If we have cache enabled // If we have cache enabled
// We generate a hash for the given binary, so we can use it as key // We generate a hash for the given binary, so we can use it as key
@ -316,6 +341,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
&wasm_binary[..], &wasm_binary[..],
CompilerConfig { CompilerConfig {
symbol_map: em_symbol_map, symbol_map: em_symbol_map,
..Default::default()
}, },
&*compiler, &*compiler,
) )
@ -327,15 +353,6 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
} }
}; };
module module
} else {
webassembly::compile_with_config_with(
&wasm_binary[..],
CompilerConfig {
symbol_map: em_symbol_map,
},
&*compiler,
)
.map_err(|e| format!("Can't compile module: {:?}", e))?
}; };
if let Some(loader) = options.loader { if let Some(loader) = options.loader {