From fba2287c543f1de0d6da3a495d14150c96b92603 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 4 Nov 2022 22:01:37 +0100 Subject: [PATCH] Fix mprotect failures by enabling cranelift-jit selinux-fix (#5204) The sample program in cranelift/filetests/src/function_runner.rs would abort with an mprotect failure under certain circumstances, see https://github.com/bytecodealliance/wasmtime/pull/4453#issuecomment-1303803222 Root cause was that enabling PROT_EXEC on the main process heap may be prohibited, depending on Linux distro and version. This only shows up in the doc test sample program because the main clif-util is multi-threaded and therefore allocations will happen on glibc's per-thread heap, which is allocated via mmap, and not the main process heap. Work around the problem by enabling the "selinux-fix" feature of the cranelift-jit crate dependency in the filetests. Note that this didn't compile out of the box, so a separate fix is also required and provided as part of this PR. Going forward, it would be preferable to always use mmap to allocate the backing memory for JITted code. --- cranelift/filetests/Cargo.toml | 2 +- cranelift/jit/src/memory.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml index c143c763473..7b8ce9b1d5c 100644 --- a/cranelift/filetests/Cargo.toml +++ b/cranelift/filetests/Cargo.toml @@ -16,7 +16,7 @@ cranelift-interpreter = { workspace = true } cranelift-native = { workspace = true } cranelift-reader = { workspace = true } cranelift-preopt = { workspace = true } -cranelift-jit = { workspace = true } +cranelift-jit = { workspace = true, features = ["selinux-fix"] } cranelift-module = { workspace = true } file-per-thread-logger = "0.1.2" filecheck = "0.5.0" diff --git a/cranelift/jit/src/memory.rs b/cranelift/jit/src/memory.rs index 08518b3c8e6..6fa369b7329 100644 --- a/cranelift/jit/src/memory.rs +++ b/cranelift/jit/src/memory.rs @@ -1,6 +1,6 @@ use cranelift_module::{ModuleError, ModuleResult}; -#[cfg(feature = "selinux-fix")] +#[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))] use memmap2::MmapMut; #[cfg(not(any(feature = "selinux-fix", windows)))] @@ -14,7 +14,7 @@ use wasmtime_jit_icache_coherence as icache_coherence; /// A simple struct consisting of a pointer and length. struct PtrLen { - #[cfg(feature = "selinux-fix")] + #[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))] map: Option, ptr: *mut u8, @@ -25,7 +25,7 @@ impl PtrLen { /// Create a new empty `PtrLen`. fn new() -> Self { Self { - #[cfg(feature = "selinux-fix")] + #[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))] map: None, ptr: ptr::null_mut(), @@ -250,10 +250,10 @@ impl Memory { fn non_protected_allocations_iter(&self) -> impl Iterator { let iter = self.allocations[self.already_protected..].iter(); - #[cfg(feature = "selinux-fix")] - return iter.filter(|&PtrLen { ref map, len, .. }| len != 0 && map.is_some()); + #[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))] + return iter.filter(|&PtrLen { ref map, len, .. }| *len != 0 && map.is_some()); - #[cfg(not(feature = "selinux-fix"))] + #[cfg(any(target_os = "windows", not(feature = "selinux-fix")))] return iter.filter(|&PtrLen { len, .. }| *len != 0); }