Update wasmtime to 0.27 (#8913)

* Update wasmtime to 0.27

A couple of notes:

- Now we are fair about unsafeness of runtime creation via an compiled artifact.
  This change was prompted by the change in wasmtime which made
  `deserialize` rightfully unsafe. Now `CodeSupplyMode` was hidden and
  the `create_runtime` now takes the blob again and there is now a new
  fn for creating a runtime with a compiled artifact.
- This is a big change for wasmtime. They switched to the modern backend
  for code generation. While this can bring performance improvements, it
  can also introduce some problems. In fact, 0.27 fixed a serious issue
  that could lead to sandbox escape. Hence we need a proper burn in.

This would require a change to PVF validation host as well.

* Filter regalloc logging
This commit is contained in:
Sergei Shulepov
2021-06-01 12:02:10 +02:00
committed by GitHub
parent dc88e6dd7e
commit 7a284fcf1d
7 changed files with 143 additions and 73 deletions
@@ -272,7 +272,7 @@ pub struct Config {
pub semantics: Semantics,
}
pub enum CodeSupplyMode<'a> {
enum CodeSupplyMode<'a> {
/// The runtime is instantiated using the given runtime blob.
Verbatim {
// Rationale to take the `RuntimeBlob` here is so that the client will be able to reuse
@@ -295,9 +295,42 @@ pub enum CodeSupplyMode<'a> {
/// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to
/// machine code, which can be computationally heavy.
///
/// The `cache_path` designates where this executor implementation can put compiled artifacts.
pub fn create_runtime(
blob: RuntimeBlob,
config: Config,
host_functions: Vec<&'static dyn Function>,
) -> std::result::Result<WasmtimeRuntime, WasmError> {
// SAFETY: this is safe because it doesn't use `CodeSupplyMode::Artifact`.
unsafe { do_create_runtime(CodeSupplyMode::Verbatim { blob }, config, host_functions) }
}
/// The same as [`create_runtime`] but takes a precompiled artifact, which makes this function
/// considerably faster than [`create_runtime`].
///
/// # Safety
///
/// The caller must ensure that the compiled artifact passed here was produced by [`prepare_runtime_artifact`].
/// Otherwise, there is a risk of arbitrary code execution with all implications.
///
/// It is ok though if the `compiled_artifact` was created by code of another version or with different
/// configuration flags. In such case the caller will receive an `Err` deterministically.
pub unsafe fn create_runtime_from_artifact(
compiled_artifact: &[u8],
config: Config,
host_functions: Vec<&'static dyn Function>,
) -> std::result::Result<WasmtimeRuntime, WasmError> {
do_create_runtime(
CodeSupplyMode::Artifact { compiled_artifact },
config,
host_functions,
)
}
/// # Safety
///
/// This is only unsafe if called with [`CodeSupplyMode::Artifact`]. See [`create_runtime_from_artifact`]
/// to get more details.
unsafe fn do_create_runtime(
code_supply_mode: CodeSupplyMode<'_>,
config: Config,
host_functions: Vec<&'static dyn Function>,
@@ -313,7 +346,8 @@ pub fn create_runtime(
}
}
let engine = Engine::new(&wasmtime_config);
let engine = Engine::new(&wasmtime_config)
.map_err(|e| WasmError::Other(format!("cannot create the engine for runtime: {}", e)))?;
let (module, snapshot_data) = match code_supply_mode {
CodeSupplyMode::Verbatim { mut blob } => {
@@ -341,6 +375,8 @@ pub fn create_runtime(
}
}
CodeSupplyMode::Artifact { compiled_artifact } => {
// SAFETY: The unsafity of `deserialize` is covered by this function. The
// responsibilities to maintain the invariants are passed to the caller.
let module = wasmtime::Module::deserialize(&engine, compiled_artifact)
.map_err(|e| WasmError::Other(format!("cannot deserialize module: {}", e)))?;
@@ -375,12 +411,12 @@ pub fn prepare_runtime_artifact(
) -> std::result::Result<Vec<u8>, WasmError> {
instrument(&mut blob, semantics);
let engine = Engine::new(&common_config());
let module = wasmtime::Module::new(&engine, &blob.serialize())
.map_err(|e| WasmError::Other(format!("cannot compile module: {}", e)))?;
module
.serialize()
.map_err(|e| WasmError::Other(format!("cannot serialize module: {}", e)))
let engine = Engine::new(&common_config())
.map_err(|e| WasmError::Other(format!("cannot create the engine: {}", e)))?;
engine
.precompile_module(&blob.serialize())
.map_err(|e| WasmError::Other(format!("cannot precompile module: {}", e)))
}
fn perform_call(