mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-24 06:01:33 +00:00
Enforce runtime memory and stack bound check when using kernel loader.
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -530,7 +530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dynasm"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"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"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"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)",
|
||||
@ -2645,7 +2645,7 @@ dependencies = [
|
||||
"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 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 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"
|
||||
|
@ -40,15 +40,12 @@ impl Token {
|
||||
}
|
||||
|
||||
/// Configuration data for the compiler
|
||||
#[derive(Default)]
|
||||
pub struct CompilerConfig {
|
||||
/// Symbol information generated from emscripten; used for more detailed debug messages
|
||||
pub symbol_map: Option<HashMap<u32, String>>,
|
||||
}
|
||||
|
||||
impl Default for CompilerConfig {
|
||||
fn default() -> CompilerConfig {
|
||||
CompilerConfig { symbol_map: None }
|
||||
}
|
||||
pub enforce_memory_bound_check: bool,
|
||||
pub enforce_stack_check: bool,
|
||||
}
|
||||
|
||||
pub trait Compiler {
|
||||
|
@ -43,6 +43,8 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
||||
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||
|
||||
fn feed_compiler_config(&mut self, config: &CompilerConfig) -> Result<(), E> { Ok(()) }
|
||||
}
|
||||
|
||||
pub struct StreamingCompiler<
|
||||
|
@ -53,6 +53,8 @@ pub fn read_module<
|
||||
middlewares: &mut MiddlewareChain,
|
||||
compiler_config: &CompilerConfig,
|
||||
) -> Result<ModuleInfo, LoadError> {
|
||||
mcg.feed_compiler_config(compiler_config)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
let mut info = ModuleInfo {
|
||||
memories: Map::new(),
|
||||
globals: Map::new(),
|
||||
|
@ -65,6 +65,8 @@ pub struct InternalCtx {
|
||||
pub dynamic_sigindices: *const SigId,
|
||||
|
||||
pub intrinsics: *const Intrinsics,
|
||||
|
||||
pub stack_lower_bound: *mut u8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -157,6 +159,8 @@ impl Ctx {
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
|
||||
intrinsics: get_intrinsics_for_module(&module.info),
|
||||
|
||||
stack_lower_bound: ::std::ptr::null_mut(),
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
@ -191,6 +195,8 @@ impl Ctx {
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
|
||||
intrinsics: get_intrinsics_for_module(&module.info),
|
||||
|
||||
stack_lower_bound: ::std::ptr::null_mut(),
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
@ -288,9 +294,13 @@ impl Ctx {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn offset_local_functions() -> u8 {
|
||||
10 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
}
|
||||
|
||||
enum InnerFunc {}
|
||||
@ -489,6 +499,11 @@ mod vm_offset_tests {
|
||||
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!(
|
||||
Ctx::offset_local_functions() as usize,
|
||||
offset_of!(Ctx => local_functions).get_byte_offset(),
|
||||
|
@ -10,7 +10,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
||||
wasmparser = "0.29.2"
|
||||
dynasm = "0.3.1"
|
||||
dynasm = "0.3.2"
|
||||
dynasmrt = "0.3.1"
|
||||
lazy_static = "1.2.0"
|
||||
byteorder = "1"
|
||||
|
@ -10,7 +10,7 @@ use smallvec::SmallVec;
|
||||
use std::ptr::NonNull;
|
||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, RunnableModule},
|
||||
backend::{Backend, RunnableModule, CompilerConfig},
|
||||
codegen::*,
|
||||
memory::MemoryType,
|
||||
module::ModuleInfo,
|
||||
@ -120,6 +120,8 @@ pub struct X64ModuleCodeGenerator {
|
||||
function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>,
|
||||
assembler: Option<Assembler>,
|
||||
func_import_count: usize,
|
||||
|
||||
config: Option<Arc<CodegenConfig>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
@ -143,6 +145,8 @@ pub struct X64FunctionCode {
|
||||
control_stack: Vec<ControlFrame>,
|
||||
machine: Machine,
|
||||
unreachable_depth: usize,
|
||||
|
||||
config: Arc<CodegenConfig>,
|
||||
}
|
||||
|
||||
enum FuncPtrInner {}
|
||||
@ -284,6 +288,12 @@ pub struct CodegenError {
|
||||
pub message: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct CodegenConfig {
|
||||
enforce_memory_bound_check: bool,
|
||||
enforce_stack_check: bool,
|
||||
}
|
||||
|
||||
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
for X64ModuleCodeGenerator
|
||||
{
|
||||
@ -295,6 +305,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
function_labels: Some(HashMap::new()),
|
||||
assembler: Some(Assembler::new().unwrap()),
|
||||
func_import_count: 0,
|
||||
config: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,6 +359,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
control_stack: vec![],
|
||||
machine: Machine::new(),
|
||||
unreachable_depth: 0,
|
||||
config: self.config.as_ref().unwrap().clone(),
|
||||
};
|
||||
self.functions.push(code);
|
||||
Ok(self.functions.last_mut().unwrap())
|
||||
@ -460,6 +472,14 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
|
||||
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 {
|
||||
@ -1173,6 +1193,7 @@ impl X64FunctionCode {
|
||||
/// Emits a memory operation.
|
||||
fn emit_memory_op<F: FnOnce(&mut Assembler, &mut Machine, GPR)>(
|
||||
module_info: &ModuleInfo,
|
||||
config: &CodegenConfig,
|
||||
a: &mut Assembler,
|
||||
m: &mut Machine,
|
||||
addr: Location,
|
||||
@ -1222,9 +1243,13 @@ impl X64FunctionCode {
|
||||
&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 {
|
||||
true
|
||||
} else {
|
||||
match mem_desc.memory_type() {
|
||||
MemoryType::Dynamic => true,
|
||||
MemoryType::Static | MemoryType::SharedStatic => false,
|
||||
}
|
||||
};
|
||||
|
||||
if need_check {
|
||||
@ -1391,6 +1416,19 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
a.emit_push(Size::S64, 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
|
||||
.machine
|
||||
.init_locals(a, self.num_locals, self.num_params);
|
||||
@ -3351,6 +3389,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3376,6 +3415,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3401,6 +3441,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3427,6 +3468,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3453,6 +3495,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3479,6 +3522,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3505,6 +3549,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3530,6 +3575,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3555,6 +3601,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3580,6 +3627,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3605,6 +3653,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3630,6 +3679,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3655,6 +3705,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3681,6 +3732,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3707,6 +3759,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3733,6 +3786,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3759,6 +3813,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3790,6 +3845,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target,
|
||||
@ -3816,6 +3872,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3841,6 +3898,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3866,6 +3924,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3891,6 +3950,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
@ -3916,6 +3976,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|
||||
Self::emit_memory_op(
|
||||
module_info,
|
||||
&self.config,
|
||||
a,
|
||||
&mut self.machine,
|
||||
target_addr,
|
||||
|
@ -50,6 +50,8 @@ fn handle_client(mut stream: UnixStream) {
|
||||
&wasm_binary[..],
|
||||
CompilerConfig {
|
||||
symbol_map: None,
|
||||
enforce_memory_bound_check: true,
|
||||
enforce_stack_check: true,
|
||||
},
|
||||
&SinglePassCompiler::new(),
|
||||
).unwrap();
|
||||
|
@ -287,7 +287,32 @@ fn execute_wasm(options: &Run) -> Result<(), 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
|
||||
|
||||
// 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[..],
|
||||
CompilerConfig {
|
||||
symbol_map: em_symbol_map,
|
||||
..Default::default()
|
||||
},
|
||||
&*compiler,
|
||||
)
|
||||
@ -327,15 +353,6 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
}
|
||||
};
|
||||
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 {
|
||||
|
Reference in New Issue
Block a user