Skip to content

Commit bfb1d65

Browse files
committed
[host/mem] added 'user memory' region to store additional guest blob
+ added some extra configuration to set the maximum memory size (needed for extra blob) + if guest blob is provided, we now write it to shared mem when creating a sandbox Signed-off-by: danbugs <[email protected]>
1 parent 82b9772 commit bfb1d65

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

src/hyperlight_host/src/mem/layout.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use crate::error::HyperlightError::{GuestOffsetIsInvalid, MemoryRequestTooBig};
3030
use crate::sandbox::SandboxConfiguration;
3131
use crate::{Result, new_error};
3232

33+
// +-------------------------------------------+
34+
// | User Memory | (guest blob size)
3335
// +-------------------------------------------+
3436
// | Guest (User) Stack |
3537
// +-------------------------------------------+
@@ -103,6 +105,7 @@ pub(crate) struct SandboxMemoryLayout {
103105
guest_heap_buffer_offset: usize,
104106
guard_page_offset: usize,
105107
guest_user_stack_buffer_offset: usize, // the lowest address of the user stack
108+
user_memory_offset: usize,
106109

107110
// other
108111
pub(crate) peb_address: usize,
@@ -181,6 +184,10 @@ impl Debug for SandboxMemoryLayout {
181184
"Guest User Stack Buffer Offset",
182185
&format_args!("{:#x}", self.guest_user_stack_buffer_offset),
183186
)
187+
.field(
188+
"User Memory Offset",
189+
&format_args!("{:#x}", self.user_memory_offset),
190+
)
184191
.field(
185192
"Page Table Size",
186193
&format_args!("{:#x}", self.total_page_table_size),
@@ -275,6 +282,7 @@ impl SandboxMemoryLayout {
275282
let guest_user_stack_buffer_offset = guard_page_offset + PAGE_SIZE_USIZE;
276283
// round up stack size to page size. This is needed for MemoryRegion
277284
let stack_size_rounded = round_up_to(stack_size, PAGE_SIZE_USIZE);
285+
let user_memory_offset = guest_user_stack_buffer_offset + stack_size_rounded;
278286

279287
Ok(Self {
280288
peb_offset,
@@ -299,6 +307,7 @@ impl SandboxMemoryLayout {
299307
guard_page_offset,
300308
total_page_table_size,
301309
guest_code_offset,
310+
user_memory_offset,
302311
})
303312
}
304313

@@ -444,7 +453,11 @@ impl SandboxMemoryLayout {
444453
/// layout.
445454
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
446455
fn get_unaligned_memory_size(&self) -> usize {
447-
self.get_top_of_user_stack_offset() + self.stack_size
456+
if self.sandbox_memory_config.get_guest_memory_size() == 0 {
457+
self.user_memory_offset
458+
} else {
459+
self.sandbox_memory_config.get_guest_memory_size()
460+
}
448461
}
449462

450463
/// get the code offset
@@ -682,12 +695,34 @@ impl SandboxMemoryLayout {
682695
}
683696

684697
// stack
685-
let final_offset = builder.push_page_aligned(
698+
let user_memory_offset = builder.push_page_aligned(
686699
self.get_guest_stack_size(),
687700
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
688701
Stack,
689702
);
690703

704+
let expected_user_memory_offset = TryInto::<usize>::try_into(self.user_memory_offset)?;
705+
706+
if user_memory_offset != expected_user_memory_offset {
707+
return Err(new_error!(
708+
"User Memory offset does not match expected User Memory offset expected: {}, actual: {}",
709+
expected_user_memory_offset,
710+
user_memory_offset
711+
));
712+
}
713+
714+
let user_region_size = self.get_memory_size()? - user_memory_offset;
715+
716+
let final_offset = if user_region_size > 0 {
717+
builder.push_page_aligned(
718+
user_region_size,
719+
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE | MemoryRegionFlags::EXECUTE,
720+
Code,
721+
)
722+
} else {
723+
user_memory_offset
724+
};
725+
691726
let expected_final_offset = TryInto::<usize>::try_into(self.get_memory_size()?)?;
692727

693728
if final_offset != expected_final_offset {
@@ -701,6 +736,21 @@ impl SandboxMemoryLayout {
701736
Ok(builder.build())
702737
}
703738

739+
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
740+
pub(crate) fn write_user_memory(
741+
&self,
742+
shared_mem: &mut ExclusiveSharedMemory,
743+
bytes: &[u8],
744+
) -> Result<(u64, usize)> {
745+
if self.user_memory_offset + bytes.len() > self.get_memory_size()? {
746+
return Err(new_error!(
747+
"Not enough memory in shared memory to write user memory, increase guest memory size with set_guest_memory_size"
748+
));
749+
}
750+
shared_mem.copy_from_slice(bytes, self.user_memory_offset)?;
751+
Ok((self.user_memory_offset as u64, bytes.len()))
752+
}
753+
704754
/// Write the finished memory layout to `shared_mem` and return
705755
/// `Ok` if successful.
706756
///

src/hyperlight_host/src/sandbox/config.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ pub struct SandboxConfiguration {
5555
/// The size of the memory buffer that is made available for input to the
5656
/// Guest Binary
5757
output_data_size: usize,
58+
/// Total guest memory size
59+
guest_memory_size: usize,
5860
/// The stack size to use in the guest sandbox. If set to 0, the stack
5961
/// size will be determined from the PE file header.
6062
///
@@ -133,6 +135,7 @@ impl SandboxConfiguration {
133135
interrupt_vcpu_sigrtmin_offset,
134136
#[cfg(gdb)]
135137
guest_debug_info,
138+
guest_memory_size: 0,
136139
#[cfg(crashdump)]
137140
guest_core_dump,
138141
}
@@ -262,6 +265,16 @@ impl SandboxConfiguration {
262265
(self.heap_size_override > 0).then_some(self.heap_size_override)
263266
}
264267

268+
/// Set the total memory size.
269+
pub fn set_guest_memory_size(&mut self, guest_memory_size: usize) {
270+
self.guest_memory_size = guest_memory_size;
271+
}
272+
273+
/// Get the total memory size.
274+
pub(crate) fn get_guest_memory_size(&self) -> usize {
275+
self.guest_memory_size
276+
}
277+
265278
/// If self.stack_size is non-zero, return it. Otherwise,
266279
/// return exe_info.stack_reserve()
267280
#[instrument(skip_all, parent = Span::current(), level= "Trace")]

src/hyperlight_host/src/sandbox/mem_mgr.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ impl MemMgrWrapper<ExclusiveSharedMemory> {
9898
let mem_size = shared_mem.mem_size();
9999
layout.write(shared_mem, SandboxMemoryLayout::BASE_ADDRESS, mem_size)
100100
}
101+
102+
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
103+
pub(super) fn write_user_memory(&mut self, user_memory: &[u8]) -> Result<()> {
104+
let mgr = self.unwrap_mgr_mut();
105+
let layout = mgr.layout;
106+
let shared_mem = mgr.get_shared_mem_mut();
107+
layout.write_user_memory(shared_mem, user_memory)?;
108+
Ok(())
109+
}
101110
}
102111

103112
impl MemMgrWrapper<HostSharedMemory> {

src/hyperlight_host/src/sandbox/uninitialized.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@ impl<'a> GuestBlob<'a> {
150150
GuestBlob::Buffer(_) => Ok(Cow::Borrowed(self)),
151151
}
152152
}
153+
154+
/// Gets the GuestBlob as bytes (for a FilePath type, it reads the file into a buffer).
155+
pub fn as_bytes(&self) -> Result<Cow<'a, [u8]>> {
156+
match self {
157+
GuestBlob::FilePath(path) => {
158+
let bytes = std::fs::read(path)
159+
.map_err(|e| new_error!("Error reading file '{}': {}", path, e))?;
160+
Ok(Cow::Owned(bytes))
161+
}
162+
GuestBlob::Buffer(buffer) => Ok(Cow::Borrowed(*buffer)),
163+
}
164+
}
153165
}
154166

155167
impl<'a> From<&'a GuestBlob<'a>> for Cow<'a, GuestBlob<'a>> {
@@ -260,13 +272,20 @@ impl UninitializedSandbox {
260272

261273
let mut mem_mgr_wrapper = {
262274
let mut mgr = UninitializedSandbox::load_guest_binary(sandbox_cfg, &guest_binary)?;
275+
263276
let stack_guard = Self::create_stack_guard();
264277
mgr.set_stack_guard(&stack_guard)?;
265278
MemMgrWrapper::new(mgr, stack_guard)
266279
};
267280

268281
mem_mgr_wrapper.write_memory_layout()?;
269282

283+
// if env has a guest blob, load it into shared mem
284+
if let Some(guest_blob) = env.guest_blob {
285+
let bytes = guest_blob.as_bytes()?;
286+
mem_mgr_wrapper.write_user_memory(&bytes)?;
287+
}
288+
270289
let host_funcs = Arc::new(Mutex::new(FunctionRegistry::default()));
271290

272291
let mut sandbox = Self {

0 commit comments

Comments
 (0)