From 556e1a1df913a83a9290d9272b0d6c069dcaf88e Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Sat, 13 Dec 2025 00:29:15 +0000 Subject: [PATCH 1/3] upcall trait and impl placeholder --- Cargo.lock | 1 + dev_tests/src/ratchet.rs | 2 +- litebox/src/lib.rs | 1 + litebox/src/upcall.rs | 29 +++++++++++++++++++ litebox_platform_lvbs/src/lib.rs | 16 ++++++++++ .../src/mshv/vsm_optee_smc.rs | 7 ++++- litebox_runner_lvbs/Cargo.toml | 2 +- litebox_runner_lvbs/src/lib.rs | 22 ++++++++++++++ 8 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 litebox/src/upcall.rs diff --git a/Cargo.lock b/Cargo.lock index c3cb77dc0..c2992cdc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -954,6 +954,7 @@ name = "litebox_runner_lvbs" version = "0.1.0" dependencies = [ "litebox", + "litebox_common_linux", "litebox_platform_lvbs", "litebox_platform_multiplex", "litebox_shim_optee", diff --git a/dev_tests/src/ratchet.rs b/dev_tests/src/ratchet.rs index 6252f8379..f7bad64a5 100644 --- a/dev_tests/src/ratchet.rs +++ b/dev_tests/src/ratchet.rs @@ -29,7 +29,7 @@ fn ratchet_globals() -> Result<()> { ("litebox/", 8), ("litebox_platform_linux_kernel/", 5), ("litebox_platform_linux_userland/", 5), - ("litebox_platform_lvbs/", 21), + ("litebox_platform_lvbs/", 22), ("litebox_platform_multiplex/", 1), ("litebox_platform_windows_userland/", 7), ("litebox_runner_linux_userland/", 1), diff --git a/litebox/src/lib.rs b/litebox/src/lib.rs index 1b64a0344..1b8030d23 100644 --- a/litebox/src/lib.rs +++ b/litebox/src/lib.rs @@ -24,6 +24,7 @@ pub mod platform; pub mod shim; pub mod sync; pub mod tls; +pub mod upcall; // The core [`LiteBox`] object itself, re-exported here publicly, just to keep management of the // code cleaner. diff --git a/litebox/src/upcall.rs b/litebox/src/upcall.rs new file mode 100644 index 000000000..f8f8f9207 --- /dev/null +++ b/litebox/src/upcall.rs @@ -0,0 +1,29 @@ +//! Types and traits to provide upcalls for platforms. +//! A platform may get some messages or requests from the host or +//! remote parties that it does not know how to handle (e.g., +//! an OP-TEE SMC call from the normal-world kernel). Rather than +//! making the platform handle all these messages or requests itself, +//! we implement upcalls to let the platform delegate handling of +//! unknown messages or requests to other layers of LiteBox (i.e., +//! runner or shim). +use thiserror::Error; + +pub trait Upcall { + /// The upcall context type + type Context; + + /// Initialize the upcall handler + fn init(&self) -> alloc::boxed::Box>; + + /// Execute the upcall with the given context + fn execute(&self, ctx: &mut Self::Context) -> Result; +} + +/// The operation to perform after returning from a shim handler +#[derive(Error, Debug)] +pub enum UpcallError { + #[error("Upcall failed")] + Failure, + #[error("Upcall needs to be retried")] + Retry, +} diff --git a/litebox_platform_lvbs/src/lib.rs b/litebox_platform_lvbs/src/lib.rs index 7498447da..c7ff84c94 100644 --- a/litebox_platform_lvbs/src/lib.rs +++ b/litebox_platform_lvbs/src/lib.rs @@ -389,6 +389,17 @@ impl LinuxKernel { ) { syscall_entry::init(shim); } + + /// Register the upcall. + pub fn register_upcall( + upcall: &'static ( + dyn litebox::upcall::Upcall + + Send + + Sync + ), + ) { + UPCALL.call_once(|| upcall); + } } impl RawMutexProvider for LinuxKernel { @@ -755,6 +766,11 @@ impl StdioProvider for LinuxKernel { } } +// Use static for upcall (we can use kernel TLS if needed) and `PtRegs` for now. +static UPCALL: spin::Once< + &'static (dyn litebox::upcall::Upcall + Send + Sync), +> = spin::Once::new(); + // NOTE: The below code is a naive workaround to let LVBS code to access the platform. // Rather than doing this, we should implement LVBS interface/provider for the platform. diff --git a/litebox_platform_lvbs/src/mshv/vsm_optee_smc.rs b/litebox_platform_lvbs/src/mshv/vsm_optee_smc.rs index 0ac94059b..c7158c717 100644 --- a/litebox_platform_lvbs/src/mshv/vsm_optee_smc.rs +++ b/litebox_platform_lvbs/src/mshv/vsm_optee_smc.rs @@ -18,7 +18,12 @@ pub(crate) fn optee_smc_dispatch(optee_smc_args_pfn: u64) -> i64 { with_per_cpu_variables_mut(|per_cpu_variables| { per_cpu_variables.save_extended_states(HV_VTL_SECURE); }); - // TODO: Implement OP-TEE SMC for TA command invocation here. + + // Placeholder for now + let upcall = crate::UPCALL.get().expect("OP-TEE upcall not registered"); + let mut ctx = litebox_common_linux::PtRegs::default(); + let _ = upcall.execute(&mut ctx); + debug_serial_println!("VSM function call for OP-TEE message"); with_per_cpu_variables_mut(|per_cpu_variables| { per_cpu_variables.restore_extended_states(HV_VTL_SECURE); diff --git a/litebox_runner_lvbs/Cargo.toml b/litebox_runner_lvbs/Cargo.toml index 30a916484..de1957b95 100644 --- a/litebox_runner_lvbs/Cargo.toml +++ b/litebox_runner_lvbs/Cargo.toml @@ -5,11 +5,11 @@ edition = "2024" [dependencies] litebox = { version = "0.1.0", path = "../litebox" } +litebox_common_linux = { path = "../litebox_common_linux/", version = "0.1.0" } litebox_platform_lvbs = { version = "0.1.0", path = "../litebox_platform_lvbs", default-features = false, features = ["interrupt"] } litebox_platform_multiplex = { version = "0.1.0", path = "../litebox_platform_multiplex", default-features = false, features = ["platform_lvbs"] } litebox_shim_optee = { path = "../litebox_shim_optee/", version = "0.1.0" } - [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = { version = "0.15.2", default-features = false, features = ["instructions"] } diff --git a/litebox_runner_lvbs/src/lib.rs b/litebox_runner_lvbs/src/lib.rs index ca136b3f0..89127c069 100644 --- a/litebox_runner_lvbs/src/lib.rs +++ b/litebox_runner_lvbs/src/lib.rs @@ -1,5 +1,7 @@ #![no_std] +extern crate alloc; + use core::panic::PanicInfo; use litebox_platform_lvbs::{ arch::{gdt, get_core_id, instrs::hlt_loop, interrupts}, @@ -91,6 +93,7 @@ pub fn init() -> Option<&'static Platform> { interrupts::init_idt(); x86_64::instructions::interrupts::enable(); Platform::register_shim(&litebox_shim_optee::OpteeShim); + Platform::register_upcall(&crate::OpteeMsgHandler); ret } @@ -99,6 +102,25 @@ pub fn run(platform: Option<&'static Platform>) -> ! { vtl_switch_loop_entry(platform) } +pub struct OpteeMsgHandler; +impl litebox::upcall::Upcall for OpteeMsgHandler { + type Context = litebox_common_linux::PtRegs; + + fn init( + &self, + ) -> alloc::boxed::Box> + { + alloc::boxed::Box::new(OpteeMsgHandler {}) + } + + fn execute( + &self, + _ctx: &mut Self::Context, + ) -> Result { + todo!("invoke OP-TEE message handlers") + } +} + #[panic_handler] fn panic(info: &PanicInfo) -> ! { serial_println!("{}", info); From eabf6a65c20cb011751f6d0447937e5ed08f7330 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Sun, 14 Dec 2025 02:38:16 +0000 Subject: [PATCH 2/3] fix comment. separate param and ret types --- litebox/src/upcall.rs | 20 ++++++++++++++------ litebox_platform_lvbs/src/lib.rs | 14 +++++++++++--- litebox_runner_lvbs/src/lib.rs | 15 ++++++++++----- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/litebox/src/upcall.rs b/litebox/src/upcall.rs index f8f8f9207..921ff9f56 100644 --- a/litebox/src/upcall.rs +++ b/litebox/src/upcall.rs @@ -9,17 +9,25 @@ use thiserror::Error; pub trait Upcall { - /// The upcall context type - type Context; + /// The upcall parameter type + type Parameter; + + /// The upcall return type + type Return; /// Initialize the upcall handler - fn init(&self) -> alloc::boxed::Box>; + fn init( + &self, + ) -> alloc::boxed::Box< + dyn crate::upcall::Upcall, + >; - /// Execute the upcall with the given context - fn execute(&self, ctx: &mut Self::Context) -> Result; + /// Execute the upcall with the given parameter + fn execute(&self, ctx: &mut Self::Parameter) -> Result; } -/// The operation to perform after returning from a shim handler +/// The error type for upcalls +#[non_exhaustive] #[derive(Error, Debug)] pub enum UpcallError { #[error("Upcall failed")] diff --git a/litebox_platform_lvbs/src/lib.rs b/litebox_platform_lvbs/src/lib.rs index c7ff84c94..b05278df3 100644 --- a/litebox_platform_lvbs/src/lib.rs +++ b/litebox_platform_lvbs/src/lib.rs @@ -393,8 +393,10 @@ impl LinuxKernel { /// Register the upcall. pub fn register_upcall( upcall: &'static ( - dyn litebox::upcall::Upcall - + Send + dyn litebox::upcall::Upcall< + Parameter = litebox_common_linux::PtRegs, + Return = litebox_common_linux::PtRegs, + > + Send + Sync ), ) { @@ -768,7 +770,13 @@ impl StdioProvider for LinuxKernel { // Use static for upcall (we can use kernel TLS if needed) and `PtRegs` for now. static UPCALL: spin::Once< - &'static (dyn litebox::upcall::Upcall + Send + Sync), + &'static ( + dyn litebox::upcall::Upcall< + Parameter = litebox_common_linux::PtRegs, + Return = litebox_common_linux::PtRegs, + > + Send + + Sync + ), > = spin::Once::new(); // NOTE: The below code is a naive workaround to let LVBS code to access the platform. diff --git a/litebox_runner_lvbs/src/lib.rs b/litebox_runner_lvbs/src/lib.rs index 89127c069..6fbd3e0dc 100644 --- a/litebox_runner_lvbs/src/lib.rs +++ b/litebox_runner_lvbs/src/lib.rs @@ -104,19 +104,24 @@ pub fn run(platform: Option<&'static Platform>) -> ! { pub struct OpteeMsgHandler; impl litebox::upcall::Upcall for OpteeMsgHandler { - type Context = litebox_common_linux::PtRegs; + type Parameter = litebox_common_linux::PtRegs; + type Return = litebox_common_linux::PtRegs; fn init( &self, - ) -> alloc::boxed::Box> - { + ) -> alloc::boxed::Box< + dyn litebox::upcall::Upcall< + Parameter = litebox_common_linux::PtRegs, + Return = litebox_common_linux::PtRegs, + >, + > { alloc::boxed::Box::new(OpteeMsgHandler {}) } fn execute( &self, - _ctx: &mut Self::Context, - ) -> Result { + _ctx: &mut Self::Parameter, + ) -> Result { todo!("invoke OP-TEE message handlers") } } From 57f874bf6aea28f08fa06f0a0625f0134edf5ac1 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Thu, 18 Dec 2025 06:25:00 +0000 Subject: [PATCH 3/3] revise comments --- litebox/src/upcall.rs | 51 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/litebox/src/upcall.rs b/litebox/src/upcall.rs index 921ff9f56..cd2ee9785 100644 --- a/litebox/src/upcall.rs +++ b/litebox/src/upcall.rs @@ -1,28 +1,53 @@ -//! Types and traits to provide upcalls for platforms. -//! A platform may get some messages or requests from the host or -//! remote parties that it does not know how to handle (e.g., -//! an OP-TEE SMC call from the normal-world kernel). Rather than -//! making the platform handle all these messages or requests itself, -//! we implement upcalls to let the platform delegate handling of -//! unknown messages or requests to other layers of LiteBox (i.e., -//! runner or shim). +//! Upcall for platforms +//! +//! This module defines types and trait to provide upcalls for platforms. +//! A platform may receive some messages or requests from the host, devices, +//! or remote parties that it does not know how to handle. Rather than +//! making the platform be aware of all these messages or requests itself, +//! we implement upcalls to let platforms delegate handling of unknown +//! messages or requests to other layers of LiteBox (i.e., runner or shim). +//! Examples of such messages or requests include HVCI/Heki requests from +//! VTL0 and OP-TEE SMC calls from the normal world. +//! +//! # Security considerations +//! +//! Unlike other upcalls like hyperupcalls from the hypervisor to a guest VM, +//! this upcall is handled within LiteBox's TCB (i.e., by either runner or shim). +//! Therefore, the security considerations for this upcall are similar to function +//! calls within LiteBox. However, care must be taken to ensure that the upcall's +//! parameters and return values are properly validated and sanitized to prevent +//! potential security vulnerabilities. This is because the parameters might be +//! provided by untrusted sources and return values might contain sensitive +//! information. We assume that the upcall providers must implement necessary +//! security checks and validations. The platform would simply pass the parameters +//! and return values between untrusted sources and upcall providers (because it +//! does not have semantics to validate them). We can specify a function for early +//! validation at the platform side if needed but its advantages are not clear at +//! this moment (since there is no costly context switch within LiteBox). + use thiserror::Error; +/// An interface for upcalls from the platform to other layers of LiteBox. pub trait Upcall { - /// The upcall parameter type + /// The upcall parameter type to be passed from the platform. type Parameter; - /// The upcall return type + /// The upcall return type to be returned to the platform. type Return; - /// Initialize the upcall handler + /// Initialize the upcall handler. Must be called by the platform exactly once. + /// Per-thread initialization is possible but all threads must share the same + /// upcall handler. fn init( &self, ) -> alloc::boxed::Box< dyn crate::upcall::Upcall, >; - /// Execute the upcall with the given parameter + /// Execute the upcall with the given parameter. Since we do not expect that the + /// platform validates the parameters, the implementation of `execute` must validate + /// parameters to avoid potential security vulnerabilities. Also, it must sanitize + /// the return values before returning them to the platform. fn execute(&self, ctx: &mut Self::Parameter) -> Result; } @@ -34,4 +59,6 @@ pub enum UpcallError { Failure, #[error("Upcall needs to be retried")] Retry, + #[error("Upcall parameter is invalid")] + InvalidParameter, }