From 299131ae2d6655c49138bfab2c4469650763ef3b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Apr 2023 11:50:48 -0500 Subject: [PATCH] Gracefully handle ENOTSUP for `memfd_create` (#6230) * Gracefully handle ENOTSUP for `memfd_create` Looks like in #6229 older kernels may not support memfd in which case we can fall back to manual memory initialization gracefully. Closes #6229 * Fix tests --- crates/runtime/src/cow.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/runtime/src/cow.rs b/crates/runtime/src/cow.rs index e043c31d11..dc87a2c27f 100644 --- a/crates/runtime/src/cow.rs +++ b/crates/runtime/src/cow.rs @@ -157,7 +157,10 @@ impl MemoryImage { use std::io::Write; - let memfd = create_memfd()?; + let memfd = match create_memfd()? { + Some(memfd) => memfd, + None => return Ok(None), + }; memfd.as_file().write_all(data)?; // Seal the memfd's data and length. @@ -237,14 +240,23 @@ impl MemoryImage { } #[cfg(target_os = "linux")] -fn create_memfd() -> Result { +fn create_memfd() -> Result> { + use std::io::ErrorKind; + // Create the memfd. It needs a name, but the // documentation for `memfd_create()` says that names can // be duplicated with no issues. - memfd::MemfdOptions::new() + match memfd::MemfdOptions::new() .allow_sealing(true) .create("wasm-memory-image") - .map_err(|e| e.into()) + { + Ok(memfd) => Ok(Some(memfd)), + // If this kernel is old enough to not support memfd then attempt to + // gracefully handle that and fall back to skipping the memfd + // optimization. + Err(memfd::Error::Create(err)) if err.kind() == ErrorKind::Unsupported => Ok(None), + Err(e) => Err(e.into()), + } } impl ModuleMemoryImages { @@ -830,12 +842,16 @@ impl Drop for MemoryImageSlot { mod test { use std::sync::Arc; - use super::{create_memfd, FdSource, MemoryImage, MemoryImageSlot, MemoryPlan, MemoryStyle}; + use super::{FdSource, MemoryImage, MemoryImageSlot, MemoryPlan, MemoryStyle}; use crate::mmap::Mmap; use anyhow::Result; use std::io::Write; use wasmtime_environ::Memory; + fn create_memfd() -> Result { + Ok(super::create_memfd()?.expect("kernel doesn't support memfd")) + } + fn create_memfd_with_data(offset: usize, data: &[u8]) -> Result { // Offset must be page-aligned. let page_size = crate::page_size();