Skip to content

Commit 6f066b5

Browse files
committed
make all guest function calls persistent
Signed-off-by: Jorge Prendes <[email protected]>
1 parent b05d88c commit 6f066b5

File tree

5 files changed

+78
-74
lines changed

5 files changed

+78
-74
lines changed

src/hyperlight_host/src/func/call_ctx.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,27 +183,27 @@ mod tests {
183183
let sbox: MultiUseSandbox = new_uninit().unwrap().evolve(Noop::default()).unwrap();
184184
Self { sandbox: sbox }
185185
}
186-
pub fn call_add_to_static_multiple_times(mut self, i: i32) -> Result<TestSandbox> {
187-
let mut ctx = self.sandbox.new_call_context();
186+
pub fn call_add_to_static_multiple_times(&mut self, i: i32) -> Result<()> {
187+
let snapshot = self.sandbox.snapshot()?;
188188
let mut sum: i32 = 0;
189189
for n in 0..i {
190-
let result = ctx.call::<i32>("AddToStatic", n);
190+
let result = self.sandbox.call_guest_function_by_name::<i32>("AddToStatic", n);
191191
sum += n;
192192
println!("{:?}", result);
193193
let result = result.unwrap();
194194
assert_eq!(result, sum);
195195
}
196-
let result = ctx.finish();
197-
assert!(result.is_ok());
198-
self.sandbox = result.unwrap();
199-
Ok(self)
196+
self.sandbox.restore(&snapshot)?;
197+
Ok(())
200198
}
201199

202-
pub fn call_add_to_static(mut self, i: i32) -> Result<()> {
200+
pub fn call_add_to_static(&mut self, i: i32) -> Result<()> {
201+
let snapshot = self.sandbox.snapshot()?;
203202
for n in 0..i {
204203
let result = self
205204
.sandbox
206205
.call_guest_function_by_name::<i32>("AddToStatic", n);
206+
self.sandbox.restore(&snapshot)?;
207207
println!("{:?}", result);
208208
let result = result.unwrap();
209209
assert_eq!(result, n);
@@ -214,14 +214,14 @@ mod tests {
214214

215215
#[test]
216216
fn ensure_multiusesandbox_multi_calls_dont_reset_state() {
217-
let sandbox = TestSandbox::new();
217+
let mut sandbox = TestSandbox::new();
218218
let result = sandbox.call_add_to_static_multiple_times(5);
219219
assert!(result.is_ok());
220220
}
221221

222222
#[test]
223223
fn ensure_multiusesandbox_single_calls_do_reset_state() {
224-
let sandbox = TestSandbox::new();
224+
let mut sandbox = TestSandbox::new();
225225
let result = sandbox.call_add_to_static(5);
226226
assert!(result.is_ok());
227227
}

src/hyperlight_host/src/mem/mgr.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,4 +542,25 @@ impl SandboxMemoryManager<HostSharedMemory> {
542542
self.layout.sandbox_memory_config.get_output_data_size(),
543543
)
544544
}
545+
546+
pub(crate) fn clear_io_buffers(&mut self) {
547+
// Clear the output data buffer
548+
loop {
549+
let Ok(_) = self.shared_mem.try_pop_buffer_into::<Vec<u8>>(
550+
self.layout.output_data_buffer_offset,
551+
self.layout.sandbox_memory_config.get_output_data_size(),
552+
) else {
553+
break;
554+
};
555+
}
556+
// Clear the input data buffer
557+
loop {
558+
let Ok(_) = self.shared_mem.try_pop_buffer_into::<Vec<u8>>(
559+
self.layout.input_data_buffer_offset,
560+
self.layout.sandbox_memory_config.get_input_data_size(),
561+
) else {
562+
break;
563+
};
564+
}
565+
}
545566
}

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -170,28 +170,10 @@ impl MultiUseSandbox {
170170
.restore_snapshot(&snapshot.inner)
171171
}
172172

173-
/// Call a guest function by name, with the given return type and arguments.
174-
#[instrument(err(Debug), skip(self, args), parent = Span::current())]
175-
pub fn call_guest_function_by_name<Output: SupportedReturnType>(
176-
&mut self,
177-
func_name: &str,
178-
args: impl ParameterTuple,
179-
) -> Result<Output> {
180-
maybe_time_and_emit_guest_call(func_name, || {
181-
let ret = self.call_guest_function_by_name_no_reset(
182-
func_name,
183-
Output::TYPE,
184-
args.into_value(),
185-
);
186-
self.restore_state()?;
187-
Output::from_value(ret?)
188-
})
189-
}
190-
191173
/// Call a guest function by name, with the given return type and arguments.
192174
/// The changes made to the sandbox are persisted
193175
#[instrument(err(Debug), skip(self, args), parent = Span::current())]
194-
pub fn persist_call_guest_function_by_name<Output: SupportedReturnType>(
176+
pub fn call_guest_function_by_name<Output: SupportedReturnType + std::fmt::Debug>(
195177
&mut self,
196178
func_name: &str,
197179
args: impl ParameterTuple,
@@ -203,7 +185,7 @@ impl MultiUseSandbox {
203185
args.into_value(),
204186
);
205187
let ret = Output::from_value(ret?);
206-
self.mem_mgr.unwrap_mgr_mut().push_state()?;
188+
self.mem_mgr.unwrap_mgr_mut().push_state().unwrap();
207189
ret
208190
})
209191
}
@@ -219,7 +201,7 @@ impl MultiUseSandbox {
219201
) -> Result<ReturnValue> {
220202
maybe_time_and_emit_guest_call(func_name, || {
221203
let ret = self.call_guest_function_by_name_no_reset(func_name, ret_type, args);
222-
self.restore_state()?;
204+
self.mem_mgr.unwrap_mgr_mut().push_state()?;
223205
ret
224206
})
225207
}
@@ -237,35 +219,43 @@ impl MultiUseSandbox {
237219
return_type: ReturnType,
238220
args: Vec<ParameterValue>,
239221
) -> Result<ReturnValue> {
240-
let fc = FunctionCall::new(
241-
function_name.to_string(),
242-
Some(args),
243-
FunctionCallType::Guest,
244-
return_type,
245-
);
246-
247-
let buffer: Vec<u8> = fc
248-
.try_into()
249-
.map_err(|_| HyperlightError::Error("Failed to serialize FunctionCall".to_string()))?;
250-
251-
self.get_mgr_wrapper_mut()
252-
.as_mut()
253-
.write_guest_function_call(&buffer)?;
254-
255-
self.vm.dispatch_call_from_host(
256-
self.dispatch_ptr.clone(),
257-
self.out_hdl.clone(),
258-
self.mem_hdl.clone(),
259-
#[cfg(gdb)]
260-
self.dbg_mem_access_fn.clone(),
261-
)?;
222+
let res = (|| {
223+
let fc = FunctionCall::new(
224+
function_name.to_string(),
225+
Some(args),
226+
FunctionCallType::Guest,
227+
return_type,
228+
);
229+
230+
let buffer: Vec<u8> = fc.try_into().map_err(|_| {
231+
HyperlightError::Error("Failed to serialize FunctionCall".to_string())
232+
})?;
262233

263-
self.check_stack_guard()?;
264-
check_for_guest_error(self.get_mgr_wrapper_mut())?;
234+
self.get_mgr_wrapper_mut()
235+
.as_mut()
236+
.write_guest_function_call(&buffer)?;
265237

266-
self.get_mgr_wrapper_mut()
267-
.as_mut()
268-
.get_guest_function_call_result()
238+
self.vm.dispatch_call_from_host(
239+
self.dispatch_ptr.clone(),
240+
self.out_hdl.clone(),
241+
self.mem_hdl.clone(),
242+
#[cfg(gdb)]
243+
self.dbg_mem_access_fn.clone(),
244+
)?;
245+
246+
self.check_stack_guard()?;
247+
check_for_guest_error(self.get_mgr_wrapper_mut())?;
248+
249+
self
250+
.get_mgr_wrapper_mut()
251+
.as_mut()
252+
.get_guest_function_call_result()
253+
})();
254+
255+
// TODO: Do we want to allow re-entrant guest function calls?
256+
self.get_mgr_wrapper_mut().as_mut().clear_io_buffers();
257+
258+
res
269259
}
270260

271261
/// Get a handle to the interrupt handler for this sandbox,
@@ -362,13 +352,14 @@ mod tests {
362352

363353
let snapshot = sbox.snapshot().unwrap();
364354

365-
sbox.persist_call_guest_function_by_name::<i32>("AddToStatic", 5i32).unwrap();
355+
sbox.call_guest_function_by_name::<i32>("AddToStatic", 5i32)
356+
.unwrap();
366357

367-
let res: i32 = sbox.persist_call_guest_function_by_name("GetStatic", ()).unwrap();
358+
let res: i32 = sbox.call_guest_function_by_name("GetStatic", ()).unwrap();
368359
assert_eq!(res, 5);
369360

370361
sbox.restore(&snapshot).unwrap();
371-
let res: i32 = sbox.persist_call_guest_function_by_name("GetStatic", ()).unwrap();
362+
let res: i32 = sbox.call_guest_function_by_name("GetStatic", ()).unwrap();
372363
assert_eq!(res, 0);
373364
}
374365

src/hyperlight_host/tests/common/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616
use hyperlight_host::func::HostFunction;
17+
use hyperlight_host::sandbox::SandboxConfiguration;
1718
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
1819
use hyperlight_host::sandbox_state::transition::Noop;
1920
use hyperlight_host::{GuestBinary, MultiUseSandbox, Result, UninitializedSandbox};
@@ -34,9 +35,12 @@ pub fn new_uninit() -> Result<UninitializedSandbox> {
3435

3536
/// Use this instead of the `new_uninit` if you want your test to only run with the rust guest, not the c guest
3637
pub fn new_uninit_rust() -> Result<UninitializedSandbox> {
38+
let mut cfg = SandboxConfiguration::default();
39+
cfg.set_input_data_size(112 * 500 + 7); // 1 MiB
40+
//cfg.set_output_data_size(500 * 100); // 1 MiB
3741
UninitializedSandbox::new(
3842
GuestBinary::FilePath(simple_guest_as_string().unwrap()),
39-
None,
43+
Some(cfg),
4044
)
4145
}
4246

src/hyperlight_host/tests/integration_test.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -688,18 +688,6 @@ fn execute_on_heap() {
688688
}
689689
}
690690

691-
#[test]
692-
fn memory_resets_after_failed_guestcall() {
693-
let mut sbox1 = new_uninit_rust().unwrap().evolve(Noop::default()).unwrap();
694-
sbox1
695-
.call_guest_function_by_name::<String>("AddToStaticAndFail", ())
696-
.unwrap_err();
697-
let res = sbox1
698-
.call_guest_function_by_name::<i32>("GetStatic", ())
699-
.unwrap();
700-
assert_eq!(res, 0, "Expected 0, got {:?}", res);
701-
}
702-
703691
// checks that a recursive function with stack allocation eventually fails with stackoverflow
704692
#[test]
705693
fn recursive_stack_allocate_overflow() {

0 commit comments

Comments
 (0)