From 6a19866da23f7dd05d9dc019bbace638d837af20 Mon Sep 17 00:00:00 2001 From: Benson Chau Date: Thu, 23 May 2019 16:14:45 -0400 Subject: [PATCH] issue #772: added an memmap replacement to support selinux --- cranelift/simplejit/Cargo.toml | 5 ++ cranelift/simplejit/src/memory.rs | 86 +++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/cranelift/simplejit/Cargo.toml b/cranelift/simplejit/Cargo.toml index a8edcd3328..b584cc490f 100644 --- a/cranelift/simplejit/Cargo.toml +++ b/cranelift/simplejit/Cargo.toml @@ -17,10 +17,15 @@ region = "2.0.0" libc = { version = "0.2.42" } errno = "0.2.4" target-lexicon = { version = "0.4.0" } +memmap = { version = "0.7.0", optional = true } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["winbase", "memoryapi"] } +[features] +selinux-fix = ['memmap'] +default = [] + [dev-dependencies] cranelift = { path = "../cranelift-umbrella", version = "0.34.0" } cranelift-frontend = { path = "../cranelift-frontend", version = "0.34.0" } diff --git a/cranelift/simplejit/src/memory.rs b/cranelift/simplejit/src/memory.rs index 0730e086ef..fde0f88871 100644 --- a/cranelift/simplejit/src/memory.rs +++ b/cranelift/simplejit/src/memory.rs @@ -1,5 +1,12 @@ +#[cfg(not(feature = "selinux-fix"))] use errno; + +#[cfg(not(feature = "selinux-fix"))] use libc; + +#[cfg(feature = "selinux-fix")] +use memmap::MmapMut; + use region; use std::mem; use std::ptr; @@ -11,6 +18,9 @@ fn round_up_to_page_size(size: usize, page_size: usize) -> usize { /// A simple struct consisting of a pointer and length. struct PtrLen { + #[cfg(feature = "selinux-fix")] + map: Option, + ptr: *mut u8, len: usize, } @@ -19,6 +29,9 @@ impl PtrLen { /// Create a new empty `PtrLen`. fn new() -> Self { Self { + #[cfg(feature = "selinux-fix")] + map: None, + ptr: ptr::null_mut(), len: 0, } @@ -26,13 +39,34 @@ impl PtrLen { /// Create a new `PtrLen` pointing to at least `size` bytes of memory, /// suitably sized and aligned for memory protection. - #[cfg(not(target_os = "windows"))] + #[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))] + fn with_size(size: usize) -> Result { + let page_size = region::page::size(); + let alloc_size = round_up_to_page_size(size, page_size); + let map = MmapMut::map_anon(alloc_size); + + match map { + Ok(mut map) => { + // The order here is important; we assign the pointer first to get + // around compile time borrow errors. + Ok(Self { + ptr: map.as_mut_ptr(), + map: Some(map), + len: alloc_size, + }) + } + Err(e) => Err(e.to_string()), + } + } + + #[cfg(all(not(target_os = "windows"), not(feature = "selinux-fix")))] fn with_size(size: usize) -> Result { let mut ptr = ptr::null_mut(); let page_size = region::page::size(); let alloc_size = round_up_to_page_size(size, page_size); unsafe { let err = libc::posix_memalign(&mut ptr, page_size, alloc_size); + if err == 0 { Ok(Self { ptr: ptr as *mut u8, @@ -122,11 +156,26 @@ impl Memory { pub fn set_readable_and_executable(&mut self) { self.finish_current(); - for &PtrLen { ptr, len } in &self.allocations[self.executable..] { - if len != 0 { - unsafe { - region::protect(ptr, len, region::Protection::ReadExecute) - .expect("unable to make memory readable+executable"); + #[cfg(feature = "selinux-fix")] + { + for &PtrLen { ref map, ptr, len } in &self.allocations[self.executable..] { + if len != 0 && map.is_some() { + unsafe { + region::protect(ptr, len, region::Protection::ReadExecute) + .expect("unable to make memory readable+executable"); + } + } + } + } + + #[cfg(not(feature = "selinux-fix"))] + { + for &PtrLen { ptr, len } in &self.allocations[self.executable..] { + if len != 0 { + unsafe { + region::protect(ptr, len, region::Protection::ReadExecute) + .expect("unable to make memory readable+executable"); + } } } } @@ -136,11 +185,26 @@ impl Memory { pub fn set_readonly(&mut self) { self.finish_current(); - for &PtrLen { ptr, len } in &self.allocations[self.executable..] { - if len != 0 { - unsafe { - region::protect(ptr, len, region::Protection::Read) - .expect("unable to make memory readonly"); + #[cfg(feature = "selinux-fix")] + { + for &PtrLen { ref map, ptr, len } in &self.allocations[self.executable..] { + if len != 0 && map.is_some() { + unsafe { + region::protect(ptr, len, region::Protection::Read) + .expect("unable to make memory readonly"); + } + } + } + } + + #[cfg(not(feature = "selinux-fix"))] + { + for &PtrLen { ptr, len } in &self.allocations[self.executable..] { + if len != 0 { + unsafe { + region::protect(ptr, len, region::Protection::Read) + .expect("unable to make memory readonly"); + } } } }