Update memfd support with a runtime toggle (#3778)

This commit updates the `memfd` support in Wasmtime to have a runtime
toggle as to whether it's used or not. The compile-time feature gating
`memfd` support is now also re-enabled by default, but the new runtime
switch is still disabled-by-default.

Additionally this commit updates our fuzz oracle to turn on/off the
memfd flag to re-enable fuzzing with memfd on oss-fuzz.
This commit is contained in:
Alex Crichton
2022-02-08 15:47:13 -06:00
committed by GitHub
parent 4f01711d42
commit 5cd97c054d
6 changed files with 62 additions and 2 deletions

View File

@@ -61,6 +61,7 @@ pub struct WasmtimeConfig {
pub(crate) consume_fuel: bool,
memory_config: MemoryConfig,
force_jump_veneers: bool,
memfd: bool,
}
#[derive(Arbitrary, Clone, Debug, Eq, Hash, PartialEq)]
@@ -99,7 +100,8 @@ impl Config {
.cranelift_nan_canonicalization(self.wasmtime.canonicalize_nans)
.cranelift_opt_level(self.wasmtime.opt_level.to_wasmtime())
.interruptable(self.wasmtime.interruptable)
.consume_fuel(self.wasmtime.consume_fuel);
.consume_fuel(self.wasmtime.consume_fuel)
.memfd(self.wasmtime.memfd);
// If the wasm-smith-generated module use nan canonicalization then we
// don't need to enable it, but if it doesn't enable it already then we

View File

@@ -51,7 +51,16 @@ wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync" }
maintenance = { status = "actively-developed" }
[features]
default = ['async', 'cache', 'wat', 'jitdump', 'parallel-compilation', 'cranelift', 'pooling-allocator']
default = [
'async',
'cache',
'wat',
'jitdump',
'parallel-compilation',
'cranelift',
'pooling-allocator',
'memfd',
]
# An on-by-default feature enabling runtime compilation of WebAssembly modules
# with the Cranelift compiler. Cranelift is the default compilation backend of

View File

@@ -104,6 +104,7 @@ pub struct Config {
pub(crate) module_version: ModuleVersionStrategy,
pub(crate) parallel_compilation: bool,
pub(crate) paged_memory_initialization: bool,
pub(crate) memfd: bool,
}
impl Config {
@@ -129,6 +130,7 @@ impl Config {
parallel_compilation: true,
// Default to paged memory initialization when using uffd on linux
paged_memory_initialization: cfg!(all(target_os = "linux", feature = "uffd")),
memfd: false,
};
#[cfg(compiler)]
{
@@ -1170,6 +1172,33 @@ impl Config {
self
}
/// Configures whether `memfd`, if supported, will be used to initialize
/// applicable module memories.
///
/// This is a Linux-specific feature since `memfd` is only supported on
/// Linux. Support for this is also enabled by default at compile time but
/// is otherwise disabled at runtime by default. This feature needs to be
/// enabled to `true` for support to be used.
///
/// Also note that even if this feature is enabled it may not be applicable
/// to all memories in all wasm modules. At this time memories must meet
/// specific criteria to be memfd-initialized:
///
/// * Only memories defined in the module can be initialized this way.
/// * Data segments for memory must use statically known offsets.
/// * Data segments for memory must all be in-bounds.
///
/// If all of the above applies, this setting is enabled, and the current
/// platform is Linux the `memfd` will be used to efficiently initialize
/// linear memories with `mmap` to avoid copying data from initializers into
/// linear memory.
#[cfg(feature = "memfd")]
#[cfg_attr(nightlydoc, doc(cfg(feature = "memfd")))]
pub fn memfd(&mut self, memfd: bool) -> &mut Self {
self.memfd = memfd;
self
}
pub(crate) fn build_allocator(&self) -> Result<Box<dyn InstanceAllocator>> {
#[cfg(feature = "async")]
let stack_size = self.async_stack_size;
@@ -1239,6 +1268,7 @@ impl Clone for Config {
module_version: self.module_version.clone(),
parallel_compilation: self.parallel_compilation,
paged_memory_initialization: self.paged_memory_initialization,
memfd: self.memfd,
}
}
}

View File

@@ -275,6 +275,21 @@
//! all architectures for both the JIT compiler and the `wasmtime compile` CLI
//! command.
//!
//! * `pooling-allocator` - Enabled by default, this feature adds support for
//! the pooling allocation strategy enabled via
//! [`Config::allocation_strategy`]. The pooling allocator can enable more
//! efficient reuse of resources for high-concurrency and
//! high-instantiation-count scenarios.
//!
//! * `memfd` - Enabled by default, this feature builds in support for a
//! Linux-specific feature of creating a `memfd` where applicable for a
//! [`Module`]'s initial memory. This makes instantiation much faster by
//! `mmap`-ing the initial memory image into place instead of copying memory
//! into place, allowing sharing pages that end up only getting read and
//! otherwise using copy-on-write for efficient initialization of memory. Note
//! that this is simply compile-time support and this must also be enabled at
//! run-time via [`Config::memfd`].
//!
//! ## Examples
//!
//! In addition to the examples below be sure to check out the [online embedding

View File

@@ -724,6 +724,9 @@ impl Module {
}
pub(crate) fn memfds(&self) -> Result<Option<&Arc<ModuleMemFds>>> {
if !self.engine().config().memfd {
return Ok(None);
}
Ok(self
.inner
.memfds