-
Notifications
You must be signed in to change notification settings - Fork 0
Implements bsan_alloc and bsan_dealloc #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: bsan
Are you sure you want to change the base?
Changes from all commits
989c53f
e0c6e53
ff55dca
793a47b
a9c4767
0218508
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,8 +30,11 @@ use crate::*; | |
#[derive(Debug)] | ||
pub struct GlobalCtx { | ||
hooks: BsanHooks, | ||
// TODO(obraunsdorf): Does the counter need to be AtomicU64, because it would weaken security | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like 32-bit platforms don't have support for
Footnotes |
||
// with a counter that wraps around often if we are on fewer-bit architectures? | ||
next_alloc_id: AtomicUsize, | ||
next_thread_id: AtomicUsize, | ||
alloc_metadata_map: BlockAllocator<AllocMetadata>, | ||
} | ||
|
||
const BSAN_MMAP_PROT: i32 = libc::PROT_READ | libc::PROT_WRITE; | ||
|
@@ -41,36 +44,53 @@ impl GlobalCtx { | |
/// Creates a new instance of `GlobalCtx` using the given `BsanHooks`. | ||
/// This function will also initialize our shadow heap | ||
fn new(hooks: BsanHooks) -> Self { | ||
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize; | ||
let alloc_metadata_size = mem::size_of::<AllocMetadata>(); | ||
debug_assert!(0 < alloc_metadata_size && alloc_metadata_size <= page_size); | ||
//let num_elements = NonZeroUsize::new(page_size / mem::size_of::<AllocMetadata>()).unwrap(); | ||
let num_elements = NonZeroUsize::new(1024).unwrap(); | ||
let block = Self::generate_block(hooks.mmap, hooks.munmap, num_elements); | ||
Self { | ||
hooks, | ||
next_alloc_id: AtomicUsize::new(AllocId::min().get()), | ||
next_thread_id: AtomicUsize::new(0), | ||
alloc_metadata_map: BlockAllocator::new(block), | ||
} | ||
} | ||
|
||
pub fn new_block<T>(&self, num_elements: NonZeroUsize) -> Block<T> { | ||
pub(crate) unsafe fn allocate_lock_location(&self) -> NonNull<MaybeUninit<AllocMetadata>> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this needs to be an |
||
match self.alloc_metadata_map.alloc() { | ||
Some(a) => a, | ||
None => { | ||
log::error!("Failed to allocate lock location"); | ||
panic!("Failed to allocate lock location"); | ||
} | ||
} | ||
} | ||
|
||
fn generate_block<T>(mmap: MMap, munmap: MUnmap, num_elements: NonZeroUsize) -> Block<T> { | ||
let layout = Layout::array::<T>(num_elements.into()).unwrap(); | ||
let size = NonZeroUsize::new(layout.size()).unwrap(); | ||
let size: NonZero<usize> = NonZeroUsize::new(layout.size()).unwrap(); | ||
|
||
debug_assert!(mmap as usize != 0); | ||
let base = unsafe { | ||
(self.hooks.mmap)( | ||
ptr::null_mut(), | ||
layout.size(), | ||
BSAN_MMAP_PROT, | ||
BSAN_MMAP_FLAGS, | ||
-1, | ||
0, | ||
) | ||
(mmap)(ptr::null_mut(), layout.size(), BSAN_MMAP_PROT, BSAN_MMAP_FLAGS, -1, 0) | ||
}; | ||
|
||
if base.is_null() { | ||
panic!("Allocation failed"); | ||
} | ||
let base = unsafe { NonNull::new_unchecked(mem::transmute(base)) }; | ||
let munmap = self.hooks.munmap; | ||
Block { size, base, munmap } | ||
let munmap = munmap; | ||
|
||
Block { num_elements, base, munmap } | ||
} | ||
|
||
pub fn new_block<T>(&self, num_elements: NonZeroUsize) -> Block<T> { | ||
Self::generate_block(self.hooks.mmap, self.hooks.munmap, num_elements) | ||
} | ||
|
||
fn allocator(&self) -> BsanAllocHooks { | ||
pub(crate) fn allocator(&self) -> BsanAllocHooks { | ||
self.hooks.alloc | ||
} | ||
|
||
|
@@ -281,7 +301,7 @@ pub unsafe fn global_ctx() -> *mut GlobalCtx { | |
} | ||
|
||
#[cfg(test)] | ||
pub mod test { | ||
pub(crate) mod test { | ||
use crate::*; | ||
|
||
unsafe extern "C" fn test_print(ptr: *const c_char) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should make the parameter something like
node: *mut T
instead of&mut self
in case there's a situation where multiple threads could call this method. I don't think that's the case at the moment, since this should only be called in the critical section when we lock the free list, but I'm uncertain about the soundness of that w.r.t aliasing