Make sure VMRange fills its memory with zeros if necessary

This commit is contained in:
Tate, Hongliang Tian 2019-04-11 19:21:02 +08:00 committed by Tate Tian
parent 862601604c
commit 2957fa99d5
4 changed files with 70 additions and 35 deletions

@ -68,6 +68,7 @@ pub struct VMAllocOptions {
addr: VMAddrOption,
growth: VMGrowthType,
description: String,
fill_zeros: bool,
}
impl VMAllocOptions {
@ -98,6 +99,11 @@ impl VMAllocOptions {
self.description = description.to_owned();
Ok(self)
}
pub fn fill_zeros(&mut self, fill_zeros: bool) -> Result<&mut Self, Error> {
self.fill_zeros = fill_zeros;
Ok(self)
}
}
impl fmt::Debug for VMAllocOptions {
@ -163,6 +169,7 @@ impl Default for VMGrowthType {
pub struct VMResizeOptions {
new_size: usize,
new_addr: VMAddrOption,
fill_zeros: bool,
}
impl VMResizeOptions {
@ -180,4 +187,9 @@ impl VMResizeOptions {
self.new_addr = new_addr;
self
}
pub fn fill_zeros(&mut self, fill_zeros: bool) -> &mut Self {
self.fill_zeros = fill_zeros;
self
}
}

@ -90,11 +90,12 @@ impl ProcessVM {
) -> Result<(VMArea, VMArea, VMArea, VMArea), Error> {
let mut addr = data_domain.get_start();
let mut alloc_vma_continuously =
|addr: &mut usize, size, flags, growth, desc| -> Result<_, Error> {
|addr: &mut usize, desc, size, flags, growth, fill_zeros| -> Result<_, Error> {
let mut options = VMAllocOptions::new(size)?;
options.addr(VMAddrOption::Fixed(*addr))?
.growth(growth)?
.description(desc)?;
.description(desc)?
.fill_zeros(fill_zeros)?;
let new_vma = data_domain.alloc_area(&options, flags)?;
*addr += size;
Ok(new_vma)
@ -103,14 +104,17 @@ impl ProcessVM {
let rx_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_X);
let rw_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_W);
let code_vma = alloc_vma_continuously(&mut addr, code_size, rx_flags, VMGrowthType::Fixed, "code_vma")?;
let data_vma = alloc_vma_continuously(&mut addr, data_size, rw_flags, VMGrowthType::Fixed, "data_vma")?;
let heap_vma = alloc_vma_continuously(&mut addr, 0, rw_flags, VMGrowthType::Upward, "heap_vma")?;
let code_vma = alloc_vma_continuously(&mut addr, "code_vma", code_size,
rx_flags, VMGrowthType::Fixed, true)?;
let data_vma = alloc_vma_continuously(&mut addr, "data_vma", data_size,
rw_flags, VMGrowthType::Fixed, true)?;
let heap_vma = alloc_vma_continuously(&mut addr, "heap_vma", 0,
rw_flags, VMGrowthType::Upward, true)?;
// Preserve the space for heap
addr += heap_size;
// After the heap is the stack
let stack_vma =
alloc_vma_continuously(&mut addr, stack_size, rw_flags, VMGrowthType::Downward, "stack_vma")?;
let stack_vma = alloc_vma_continuously(&mut addr, "stack_vma", stack_size,
rw_flags, VMGrowthType::Downward, false)?;
Ok((code_vma, data_vma, heap_vma, stack_vma))
}
@ -191,7 +195,7 @@ impl ProcessVM {
.iter()
.position(|vma| vma.get_start() == addr && vma.get_end() == addr + size);
if mmap_vma_i.is_none() {
return Ok(());
return errno!(EINVAL, "memory area not found");
}
mmap_vma_i.unwrap()
};
@ -221,12 +225,12 @@ impl ProcessVM {
} else if new_brk < heap_start {
return errno!(EINVAL, "New brk address is too low");
} else if new_brk > heap_end {
// TODO: init the memory with zeros for the expanded area
let resize_options = {
let new_heap_end = align_up(new_brk, 4096);
let new_heap_end = align_up(new_brk, PAGE_SIZE);
let new_heap_size = new_heap_end - heap_start;
let mut options = VMResizeOptions::new(new_heap_size)?;
options.addr(VMAddrOption::Fixed(heap_start));
options.addr(VMAddrOption::Fixed(heap_start))
.fill_zeros(true);
options
};
let heap_vma = self.heap_vma.as_mut().unwrap();

@ -59,14 +59,6 @@ impl VMDomain {
flags: VMAreaFlags,
) -> Result<VMArea, Error> {
let new_range = self.range.alloc_subrange(options)?;
// Init the memory area with all zeros
unsafe {
let mem_ptr = new_range.get_start() as *mut c_void;
let mem_size = new_range.get_size() as size_t;
memset(mem_ptr, 0 as c_int, mem_size);
}
Ok(VMArea {
range: new_range,
flags: flags,
@ -82,16 +74,10 @@ impl VMDomain {
area: &mut VMArea,
options: &VMResizeOptions,
) -> Result<(), Error> {
// TODO: init memory with zeros when expanding!
self.range.resize_subrange(&mut area.range, options)
}
}
#[link(name = "sgx_tstdc")]
extern "C" {
pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
}
#[derive(Debug)]
pub struct VMArea {

@ -81,6 +81,15 @@ impl VMRange {
self.get_subranges_mut()
.insert(new_subrange_idx, new_subrange_inner);
if options.fill_zeros {
// Init the memory area with all zeros
unsafe {
let mem_ptr = new_subrange_inner.get_start() as *mut c_void;
let mem_size = new_subrange_inner.get_size() as size_t;
memset(mem_ptr, 0 as c_int, mem_size);
}
}
// Although there are two copies of the newly created VMRangeInner obj,
// we can keep them in sync as all mutation on VMRange object must
// be carried out through dealloc_subrange() and resize_subrange() that
@ -140,7 +149,7 @@ impl VMRange {
}
// Grow
else {
self.grow_subrange_to(subrange, new_size)
self.grow_subrange_to(subrange, new_size, options.fill_zeros)
}
}
@ -340,39 +349,58 @@ impl VMRange {
Ok(())
}
fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) -> Result<(), Error> {
fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize, fill_zeros: bool) -> Result<(), Error> {
let subrange_i = self.position_subrange(subrange);
let subranges = self.get_subranges_mut();
let subrange_old_start = subrange.inner.start;
let subrange_old_end = subrange.inner.end;
let subrange_old_size = subrange.get_size();
if subrange.inner.growth == VMGrowthType::Upward {
// Can we grow?
// Can we grow upward?
let max_new_size = {
let next_subrange = &subranges[subrange_i + 1];
next_subrange.start - subrange.inner.start
next_subrange.start - subrange_old_start
};
if new_size > max_new_size {
return errno!(ENOMEM, "Cannot grow to new size");
}
// Do grow
let subrange_new_end = subrange.inner.start + new_size;
let subrange_new_end = subrange_old_start + new_size;
subrange.inner.end = subrange_new_end;
// Sync state
subranges[subrange_i].end = subrange_new_end;
} else {
// self.growth == VMGrowthType::Downward
// Can we grow?
// Init memory
if fill_zeros {
unsafe {
let mem_ptr = subrange_old_end as *mut c_void;
let mem_size = (subrange_new_end - subrange_old_end) as size_t;
memset(mem_ptr, 0 as c_int, mem_size);
}
}
} else { // self.growth == VMGrowthType::Downward
// Can we grow downard?
let max_new_size = {
let pre_subrange = &subranges[subrange_i - 1];
subrange.inner.end - pre_subrange.end
subrange_old_end - pre_subrange.end
};
if new_size > max_new_size {
return errno!(ENOMEM, "Cannot grow to new size");
}
// Do grow
let subrange_new_start = subrange.inner.end - new_size;
let subrange_new_start = subrange_old_end - new_size;
subrange.inner.start = subrange_new_start;
// Sync state
subranges[subrange_i].start = subrange_new_start;
// Init memory
if fill_zeros {
unsafe {
let mem_ptr = subrange_new_start as *mut c_void;
let mem_size = (subrange_old_start - subrange_new_start) as size_t;
memset(mem_ptr, 0 as c_int, mem_size);
}
}
}
Ok(())
}
@ -532,3 +560,8 @@ impl PartialOrd for FreeSpace {
}
}
}
#[link(name = "sgx_tstdc")]
extern "C" {
pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
}