@@ -30,6 +30,8 @@ use crate::error::HyperlightError::{GuestOffsetIsInvalid, MemoryRequestTooBig};
3030use crate :: sandbox:: SandboxConfiguration ;
3131use 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 ///
0 commit comments