-
Notifications
You must be signed in to change notification settings - Fork 17
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
Security-harden the guest's memory allocator #726
Changes from 1 commit
73b4779
e46fd05
37d2990
6f6d1bb
f03b5d0
79dff28
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 |
---|---|---|
|
@@ -4,26 +4,34 @@ | |
use core::alloc::{GlobalAlloc, Layout}; | ||
|
||
struct SimpleAllocator { | ||
next_alloc: usize, | ||
next_alloc: *mut u8, | ||
} | ||
|
||
extern "C" { | ||
// The address of this variable is the start of the heap (growing upwards). | ||
static mut _sheap: u8; | ||
} | ||
|
||
#[global_allocator] | ||
static mut HEAP: SimpleAllocator = SimpleAllocator { | ||
next_alloc: &raw mut _sheap, | ||
}; | ||
|
||
unsafe impl GlobalAlloc for SimpleAllocator { | ||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | ||
// SAFETY: Single threaded, so nothing else can touch this while we're working. | ||
let mut heap_pos = HEAP.next_alloc; | ||
|
||
let align = layout.align(); | ||
// `Layout` contract forbids making a `Layout` with align=0, or align not power of 2. | ||
// So we can safely use subtraction and a mask to ensure alignment without worrying about UB. | ||
let offset = heap_pos & (align - 1); | ||
if offset != 0 { | ||
heap_pos = heap_pos.strict_add(align.strict_sub(offset)); | ||
} | ||
core::hint::assert_unchecked(align.is_power_of_two()); | ||
core::hint::assert_unchecked(align != 0); | ||
heap_pos = heap_pos.add(heap_pos.align_offset(align)); | ||
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. We use the proper Rust functions for working with pointers now. That makes both the type checker happier (when working with pointers instead of But the latter would just be a welcome side effect, if it does happen. |
||
|
||
let ptr = heap_pos as *mut u8; | ||
let ptr = heap_pos; | ||
// Panic on overflow. We don't want to wrap around, and overwrite stack etc. | ||
// (We could also return a null pointer, but only malicious programs would ever hit this.) | ||
heap_pos = heap_pos.strict_add(layout.size()); | ||
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. Alas, |
||
heap_pos = heap_pos.add(layout.size()); | ||
|
||
HEAP.next_alloc = heap_pos; | ||
ptr | ||
|
@@ -36,14 +44,3 @@ unsafe impl GlobalAlloc for SimpleAllocator { | |
/// Never deallocate. | ||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} | ||
} | ||
|
||
#[global_allocator] | ||
// We initialize `next_alloc` to 0xFFFF_FFFF to indicate that the heap has not been initialized. | ||
// The value is chosen to make any premature allocation fail. | ||
static mut HEAP: SimpleAllocator = SimpleAllocator { | ||
next_alloc: 0xFFFF_FFFF, | ||
}; | ||
|
||
pub unsafe fn init_heap() { | ||
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. We no longer need |
||
HEAP.next_alloc = core::ptr::from_ref::<u8>(&crate::_sheap).cast::<u8>() as usize; | ||
} |
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.
This type is more truthful, and simplifies our code.