Skip to content

Commit 8a68a7e

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 cd253d8 commit 8a68a7e

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
// +-------------------------------------------+
@@ -95,6 +97,7 @@ pub(crate) struct SandboxMemoryLayout {
9597
guest_heap_buffer_offset: usize,
9698
guard_page_offset: usize,
9799
guest_user_stack_buffer_offset: usize, // the lowest address of the user stack
100+
user_memory_offset: usize,
98101

99102
// other
100103
pub(crate) peb_address: usize,
@@ -165,6 +168,10 @@ impl Debug for SandboxMemoryLayout {
165168
"Guest User Stack Buffer Offset",
166169
&format_args!("{:#x}", self.guest_user_stack_buffer_offset),
167170
)
171+
.field(
172+
"User Memory Offset",
173+
&format_args!("{:#x}", self.user_memory_offset),
174+
)
168175
.field(
169176
"Page Table Size",
170177
&format_args!("{:#x}", self.total_page_table_size),
@@ -252,6 +259,7 @@ impl SandboxMemoryLayout {
252259
let guest_user_stack_buffer_offset = guard_page_offset + PAGE_SIZE_USIZE;
253260
// round up stack size to page size. This is needed for MemoryRegion
254261
let stack_size_rounded = round_up_to(stack_size, PAGE_SIZE_USIZE);
262+
let user_memory_offset = guest_user_stack_buffer_offset + stack_size_rounded;
255263

256264
Ok(Self {
257265
peb_offset,
@@ -274,6 +282,7 @@ impl SandboxMemoryLayout {
274282
guard_page_offset,
275283
total_page_table_size,
276284
guest_code_offset,
285+
user_memory_offset,
277286
})
278287
}
279288

@@ -403,7 +412,11 @@ impl SandboxMemoryLayout {
403412
/// layout.
404413
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
405414
fn get_unaligned_memory_size(&self) -> usize {
406-
self.get_top_of_user_stack_offset() + self.stack_size
415+
if self.sandbox_memory_config.get_guest_memory_size() == 0 {
416+
self.user_memory_offset
417+
} else {
418+
self.sandbox_memory_config.get_guest_memory_size()
419+
}
407420
}
408421

409422
/// get the code offset
@@ -620,12 +633,34 @@ impl SandboxMemoryLayout {
620633
}
621634

622635
// stack
623-
let final_offset = builder.push_page_aligned(
636+
let user_memory_offset = builder.push_page_aligned(
624637
self.get_guest_stack_size(),
625638
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE,
626639
Stack,
627640
);
628641

642+
let expected_user_memory_offset = TryInto::<usize>::try_into(self.user_memory_offset)?;
643+
644+
if user_memory_offset != expected_user_memory_offset {
645+
return Err(new_error!(
646+
"User Memory offset does not match expected User Memory offset expected: {}, actual: {}",
647+
expected_user_memory_offset,
648+
user_memory_offset
649+
));
650+
}
651+
652+
let user_region_size = self.get_memory_size()? - user_memory_offset;
653+
654+
let final_offset = if user_region_size > 0 {
655+
builder.push_page_aligned(
656+
user_region_size,
657+
MemoryRegionFlags::READ | MemoryRegionFlags::WRITE | MemoryRegionFlags::EXECUTE,
658+
Code,
659+
)
660+
} else {
661+
user_memory_offset
662+
};
663+
629664
let expected_final_offset = TryInto::<usize>::try_into(self.get_memory_size()?)?;
630665

631666
if final_offset != expected_final_offset {
@@ -639,6 +674,21 @@ impl SandboxMemoryLayout {
639674
Ok(builder.build())
640675
}
641676

677+
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
678+
pub(crate) fn write_user_memory(
679+
&self,
680+
shared_mem: &mut ExclusiveSharedMemory,
681+
bytes: &[u8],
682+
) -> Result<(u64, usize)> {
683+
if self.user_memory_offset + bytes.len() > self.get_memory_size()? {
684+
return Err(new_error!(
685+
"Not enough memory in shared memory to write user memory, increase guest memory size with set_guest_memory_size"
686+
));
687+
}
688+
shared_mem.copy_from_slice(bytes, self.user_memory_offset)?;
689+
Ok((self.user_memory_offset as u64, bytes.len()))
690+
}
691+
642692
/// Write the finished memory layout to `shared_mem` and return
643693
/// `Ok` if successful.
644694
///

src/hyperlight_host/src/sandbox/config.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ pub struct SandboxConfiguration {
5252
/// The size of the memory buffer that is made available for input to the
5353
/// Guest Binary
5454
output_data_size: usize,
55+
/// Total guest memory size
56+
guest_memory_size: usize,
5557
/// The stack size to use in the guest sandbox. If set to 0, the stack
5658
/// size will be determined from the PE file header.
5759
///
@@ -119,6 +121,7 @@ impl SandboxConfiguration {
119121
interrupt_vcpu_sigrtmin_offset,
120122
#[cfg(gdb)]
121123
guest_debug_info,
124+
guest_memory_size: 0,
122125
#[cfg(crashdump)]
123126
guest_core_dump,
124127
}
@@ -233,6 +236,16 @@ impl SandboxConfiguration {
233236
(self.heap_size_override > 0).then_some(self.heap_size_override)
234237
}
235238

239+
/// Set the total memory size.
240+
pub fn set_guest_memory_size(&mut self, guest_memory_size: usize) {
241+
self.guest_memory_size = guest_memory_size;
242+
}
243+
244+
/// Get the total memory size.
245+
pub(crate) fn get_guest_memory_size(&self) -> usize {
246+
self.guest_memory_size
247+
}
248+
236249
/// If self.stack_size is non-zero, return it. Otherwise,
237250
/// return exe_info.stack_reserve()
238251
#[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)