Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extra validation to compilers & engines #2693

Merged
merged 7 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions lib/api/src/sys/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ pub enum InstantiationError {
#[error(transparent)]
Start(RuntimeError),

/// The module was compiled with a CPU feature that is not available on
/// the current host.
#[error("missing requires CPU features: {0:?}")]
CpuFeature(String),

/// Error occurred when initializing the host environment.
#[error(transparent)]
HostEnvInitialization(HostEnvInitError),
Expand All @@ -68,6 +73,7 @@ impl From<wasmer_engine::InstantiationError> for InstantiationError {
match other {
wasmer_engine::InstantiationError::Link(e) => Self::Link(e),
wasmer_engine::InstantiationError::Start(e) => Self::Start(e),
wasmer_engine::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions lib/c-api/src/wasm_c_api/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ pub unsafe extern "C" fn wasm_instance_new(
return None;
}

Err(e @ InstantiationError::CpuFeature(_)) => {
crate::error::update_last_error(e.to_string());

return None;
}

Err(InstantiationError::HostEnvInitialization(error)) => {
crate::error::update_last_error(error);

Expand Down
2 changes: 1 addition & 1 deletion lib/compiler-cranelift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ more-asserts = "0.2"
gimli = { version = "0.25", optional = true }
smallvec = "1.6"
loupe = "0.1"
target-lexicon = { version = "0.12.2", default-features = false }

[dev-dependencies]
target-lexicon = { version = "0.12.2", default-features = false }
cranelift-codegen = { version = "0.76", features = ["all-arch"] }
lazy_static = "1.4"

Expand Down
61 changes: 32 additions & 29 deletions lib/compiler-cranelift/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use gimli::write::{Address, EhFrame, FrameTable};
use loupe::MemoryUsage;
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
use std::sync::Arc;
use target_lexicon::{Architecture, OperatingSystem};
use wasmer_compiler::CompileError;
use wasmer_compiler::{CallingConvention, ModuleTranslationState, Target};
use wasmer_compiler::{
Expand All @@ -29,14 +30,12 @@ use wasmer_compiler::{
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
SectionIndex,
};
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
use wasmer_compiler::{
CustomSection, CustomSectionProtection, Relocation, RelocationKind, RelocationTarget,
SectionBody,
};
use wasmer_types::entity::{EntityRef, PrimaryMap};
use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
use wasmer_vm::libcalls::LibCall;

/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
Expand Down Expand Up @@ -111,28 +110,36 @@ impl Compiler for CraneliftCompiler {

let mut custom_sections = PrimaryMap::new();

#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
let probestack_trampoline = CustomSection {
protection: CustomSectionProtection::ReadExecute,
// We create a jump to an absolute 64bits address
// with an indrect jump immediatly followed but the absolute address
// JMP [IP+0] FF 25 00 00 00 00
// 64bits ADDR 00 00 00 00 00 00 00 00 preset to 0 until the relocation takes place
bytes: SectionBody::new_with_vec(vec![
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]),
relocations: vec![Relocation {
kind: RelocationKind::Abs8,
reloc_target: RelocationTarget::LibCall(LibCall::Probestack),
// 6 is the size of the jmp instruction. The relocated address must follow
offset: 6,
addend: 0,
}],
let probestack_trampoline_relocation_target = if target.triple().operating_system
== OperatingSystem::Linux
&& matches!(
target.triple().architecture,
Architecture::X86_32(_) | Architecture::X86_64
) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code will not work on 32bits x86. the ff 25 00 00 00 00 translate to jmp [0x00000000].
Or the offset needs to be 2 instead of 6 in 32bits

let probestack_trampoline = CustomSection {
protection: CustomSectionProtection::ReadExecute,
// We create a jump to an absolute 64bits address
// with an indrect jump immediatly followed but the absolute address
// JMP [IP+0] FF 25 00 00 00 00
// 64bits ADDR 00 00 00 00 00 00 00 00 preset to 0 until the relocation takes place
bytes: SectionBody::new_with_vec(vec![
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
]),
relocations: vec![Relocation {
kind: RelocationKind::Abs8,
reloc_target: RelocationTarget::LibCall(LibCall::Probestack),
// 6 is the size of the jmp instruction. The relocated address must follow
offset: 6,
addend: 0,
}],
};
custom_sections.push(probestack_trampoline);

Some(SectionIndex::new(custom_sections.len() - 1))
} else {
None
};
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
custom_sections.push(probestack_trampoline);
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
let probestack_trampoline_relocation_target = SectionIndex::new(custom_sections.len() - 1);

let functions = function_body_inputs
.iter()
Expand Down Expand Up @@ -170,12 +177,8 @@ impl Compiler for CraneliftCompiler {
)?;

let mut code_buf: Vec<u8> = Vec::new();
let mut reloc_sink = RelocSink::new(
&module,
func_index,
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
probestack_trampoline_relocation_target,
);
let mut reloc_sink =
RelocSink::new(&module, func_index, probestack_trampoline_relocation_target);
let mut trap_sink = TrapSink::new();
let mut stackmap_sink = binemit::NullStackMapSink {};
context
Expand Down
16 changes: 5 additions & 11 deletions lib/compiler-cranelift/src/sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

use crate::translator::{irlibcall_to_libcall, irreloc_to_relocationkind};
use cranelift_codegen::binemit;
#[cfg(target_arch = "x86_64")]
use cranelift_codegen::ir::LibCall;
use cranelift_codegen::ir::{self, ExternalName};
use cranelift_entity::EntityRef as CraneliftEntityRef;
use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, TrapInformation};
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
use wasmer_compiler::{RelocationKind, SectionIndex};
use wasmer_types::entity::EntityRef;
use wasmer_types::{FunctionIndex, LocalFunctionIndex, ModuleInfo};
Expand All @@ -24,8 +22,7 @@ pub(crate) struct RelocSink<'a> {
pub func_relocs: Vec<Relocation>,

/// The section where the probestack trampoline call is located
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
pub probestack_trampoline_relocation_target: SectionIndex,
pub probestack_trampoline_relocation_target: Option<SectionIndex>,
}

impl<'a> binemit::RelocSink for RelocSink<'a> {
Expand All @@ -45,13 +42,12 @@ impl<'a> binemit::RelocSink for RelocSink<'a> {
.expect("The provided function should be local"),
)
} else if let ExternalName::LibCall(libcall) = *name {
match libcall {
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
LibCall::Probestack => {
match (libcall, self.probestack_trampoline_relocation_target) {
(LibCall::Probestack, Some(probestack_trampoline_relocation_target)) => {
self.func_relocs.push(Relocation {
kind: RelocationKind::X86CallPCRel4,
reloc_target: RelocationTarget::CustomSection(
self.probestack_trampoline_relocation_target,
probestack_trampoline_relocation_target,
),
offset: offset,
addend: addend,
Expand Down Expand Up @@ -100,8 +96,7 @@ impl<'a> RelocSink<'a> {
pub fn new(
module: &'a ModuleInfo,
func_index: FunctionIndex,
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
probestack_trampoline_relocation_target: SectionIndex,
probestack_trampoline_relocation_target: Option<SectionIndex>,
) -> Self {
let local_func_index = module
.local_func_index(func_index)
Expand All @@ -110,7 +105,6 @@ impl<'a> RelocSink<'a> {
module,
local_func_index,
func_relocs: Vec::new(),
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
probestack_trampoline_relocation_target,
}
}
Expand Down
13 changes: 9 additions & 4 deletions lib/compiler-singlepass/src/codegen_x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ pub struct FuncGen<'a> {
///
// Ordered by increasing InstructionAddressMap::srcloc.
instructions_address_map: Vec<InstructionAddressMap>,

/// Calling convention to use.
calling_convention: CallingConvention,
}

struct SpecialLabelSet {
Expand Down Expand Up @@ -1012,7 +1015,7 @@ impl<'a> FuncGen<'a> {
self.machine.state.stack_values.push(content);
}
}
let calling_convention = self.config.calling_convention;
let calling_convention = self.calling_convention;

let stack_padding: usize = match calling_convention {
CallingConvention::WindowsFastcall => 32,
Expand Down Expand Up @@ -1758,7 +1761,7 @@ impl<'a> FuncGen<'a> {
&mut self.assembler,
self.local_types.len(),
self.signature.params().len(),
self.config.calling_convention,
self.calling_convention,
);

// Mark vmctx register. The actual loading of the vmctx value is handled by init_local.
Expand Down Expand Up @@ -1825,6 +1828,7 @@ impl<'a> FuncGen<'a> {
_table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
local_func_index: LocalFunctionIndex,
local_types_excluding_arguments: &[WpType],
calling_convention: CallingConvention,
) -> Result<FuncGen<'a>, CodegenError> {
let func_index = module.func_index(local_func_index);
let sig_index = module.functions[func_index];
Expand Down Expand Up @@ -1876,6 +1880,7 @@ impl<'a> FuncGen<'a> {
special_labels,
src_loc: 0,
instructions_address_map: vec![],
calling_convention,
};
fg.emit_head()?;
Ok(fg)
Expand Down Expand Up @@ -5406,7 +5411,7 @@ impl<'a> FuncGen<'a> {
self.vmoffsets.vmcaller_checked_anyfunc_func_ptr() as usize;
let vmcaller_checked_anyfunc_vmctx =
self.vmoffsets.vmcaller_checked_anyfunc_vmctx() as usize;
let calling_convention = self.config.calling_convention;
let calling_convention = self.calling_convention;

self.emit_call_native(
|this| {
Expand Down Expand Up @@ -6700,7 +6705,7 @@ impl<'a> FuncGen<'a> {
self.machine.finalize_locals(
&mut self.assembler,
&self.locals,
self.config.calling_convention,
self.calling_convention,
);
self.assembler.emit_mov(
Size::S64,
Expand Down
14 changes: 11 additions & 3 deletions lib/compiler-singlepass/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use std::sync::Arc;
use wasmer_compiler::{
Architecture, CallingConvention, Compilation, CompileError, CompileModuleInfo,
CompiledFunction, Compiler, CompilerConfig, FunctionBinaryReader, FunctionBody,
CompiledFunction, Compiler, CompilerConfig, CpuFeature, FunctionBinaryReader, FunctionBody,
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
ModuleTranslationState, OperatingSystem, SectionIndex, Target, TrapInformation,
};
Expand Down Expand Up @@ -62,8 +62,15 @@ impl Compiler for SinglepassCompiler {
OperatingSystem::Windows.to_string(),
));
}*/
if let Architecture::X86_32(arch) = target.triple().architecture {
return Err(CompileError::UnsupportedTarget(arch.to_string()));
if target.triple().architecture != Architecture::X86_64 {
return Err(CompileError::UnsupportedTarget(
target.triple().architecture.to_string(),
));
}
if !target.cpu_features().contains(CpuFeature::AVX) {
return Err(CompileError::UnsupportedTarget(
"x86_64 without AVX".to_string(),
));
}
if compile_info.features.multi_value {
return Err(CompileError::UnsupportedFeature("multivalue".to_string()));
Expand Down Expand Up @@ -125,6 +132,7 @@ impl Compiler for SinglepassCompiler {
&table_styles,
i,
&locals,
calling_convention,
)
.map_err(to_compile_error)?;

Expand Down
12 changes: 1 addition & 11 deletions lib/compiler-singlepass/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
use crate::compiler::SinglepassCompiler;
use loupe::MemoryUsage;
use std::sync::Arc;
use wasmer_compiler::{
CallingConvention, Compiler, CompilerConfig, CpuFeature, ModuleMiddleware, Target,
};
use wasmer_compiler::{Compiler, CompilerConfig, CpuFeature, ModuleMiddleware, Target};
use wasmer_types::Features;

#[derive(Debug, Clone, MemoryUsage)]
Expand All @@ -15,8 +13,6 @@ pub struct Singlepass {
pub(crate) enable_stack_check: bool,
/// The middleware chain.
pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
#[loupe(skip)]
pub(crate) calling_convention: CallingConvention,
}

impl Singlepass {
Expand All @@ -27,12 +23,6 @@ impl Singlepass {
enable_nan_canonicalization: true,
enable_stack_check: false,
middlewares: vec![],
calling_convention: match Target::default().triple().default_calling_convention() {
Ok(CallingConvention::WindowsFastcall) => CallingConvention::WindowsFastcall,
Ok(CallingConvention::SystemV) => CallingConvention::SystemV,
//Ok(CallingConvention::AppleAarch64) => AppleAarch64,
_ => panic!("Unsupported Calling convention for Singlepass"),
},
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/engine-dylib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ tempfile = "3.1"
which = "4.0"
rkyv = "0.6.1"
loupe = "0.1"
enumset = "1.0"

[features]
# Enable the `compiler` feature if you want the engine to compile
Expand Down
Loading