diff --git a/apps/app-loader/src/main.rs b/apps/app-loader/src/main.rs index c37fbca88..a62acc116 100644 --- a/apps/app-loader/src/main.rs +++ b/apps/app-loader/src/main.rs @@ -51,7 +51,7 @@ fn main() -> ! { let mut apps = Vec::new(); // start off by adding hello world - let buf = Buffer::into_buf(LoadAppRequest { name: xous_ipc::String::from_str("hello") }).expect("Couldn't create buffer"); + let buf = Buffer::into_buf(LoadAppRequest { name: xous_ipc::String::from_str("Hello") }).expect("Couldn't create buffer"); buf.send(self_conn, Opcode::LoadApp.to_u32().unwrap()).expect("Couldn't send message"); @@ -76,6 +76,9 @@ fn main() -> ! { .unwrap(); log::info!("Result of ping: {:?}", result); + // add its name to GAM + gam.register_name(load_app_req.name.to_str(), auth).expect("Couldn't register name"); + // load the app from the binary file let bin = include_bytes!("../../../target/riscv32imac-unknown-xous-elf/debug/hello"); let bin_len = bin.len(); diff --git a/services/gam/Cargo.toml b/services/gam/Cargo.toml index d1a06fe38..6a0ef95b8 100644 --- a/services/gam/Cargo.toml +++ b/services/gam/Cargo.toml @@ -52,4 +52,3 @@ tts = [] # default = ["debugprint"] # "debugprint" default = [] ditherpunk = [] -app_loader = [] \ No newline at end of file diff --git a/services/gam/src/api.rs b/services/gam/src/api.rs index 9c6b12767..82b79e999 100644 --- a/services/gam/src/api.rs +++ b/services/gam/src/api.rs @@ -110,6 +110,11 @@ pub struct UxRegistration { /// If the LayoutType is not an App, this field is ignored and does nothing pub focuschange_id: Option, } +#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Copy, Clone)] +pub struct NameRegistration { + pub name: String::<128>, + pub auth_token: [u32; 4], +} #[derive(Debug, num_derive::FromPrimitive, num_derive::ToPrimitive)] @@ -211,6 +216,9 @@ pub(crate) enum Opcode { /// Allow main menu activation. Used by the PDDB to turn ungate the main menu once it is mounted. /// This resolves race conditions that depend upon the PDDB configurations. AllowMainMenu = 33, + + /// Register a name that can aquire a token. This is only intended to be used with pre-registered apps + RegisterName = 34, } // small wart -- we have to reset the size of a modal to max size for resize computations diff --git a/services/gam/src/contexts.rs b/services/gam/src/contexts.rs index 02022669c..c295e00d6 100644 --- a/services/gam/src/contexts.rs +++ b/services/gam/src/contexts.rs @@ -130,6 +130,9 @@ impl ContextManager { pub(crate) fn claim_token(&mut self, name: &str) -> Option<[u32; 4]> { self.tm.claim_token(name) } + pub(crate) fn register_name(&mut self, name: &str, auth_token: &[u32; 4]) { + self.tm.register_name(name, auth_token); + } pub(crate) fn allow_untrusted_code(&self) -> bool { self.tm.allow_untrusted_code() } diff --git a/services/gam/src/lib.rs b/services/gam/src/lib.rs index 9c83c1bec..6e6a78594 100644 --- a/services/gam/src/lib.rs +++ b/services/gam/src/lib.rs @@ -309,6 +309,15 @@ impl Gam { Ok(returned_claim.token) } + pub fn register_name(&self, name: &str, auth_token: [u32; 4]) -> Result<(), xous::Error> { + let name_registration = NameRegistration { + name: String::<128>::from_str(name), + auth_token + }; + let buf = Buffer::into_buf(name_registration).or(Err(xous::Error::InternalError))?; + buf.lend(self.conn, Opcode::RegisterName.to_u32().unwrap()).or(Err(xous::Error::InternalError))?; + Ok(()) + } pub fn set_predictor_api_token(&self, api_token: [u32; 4], gam_token: [u32; 4]) -> Result<(), xous::Error> { let at = ApiToken { gam_token, diff --git a/services/gam/src/main.rs b/services/gam/src/main.rs index 165d117b8..4b579ac31 100644 --- a/services/gam/src/main.rs +++ b/services/gam/src/main.rs @@ -668,6 +668,11 @@ fn wrapped_main() -> ! { context_mgr.allow_mainmenu(); xous::return_scalar(msg.sender, 0).ok(); } + Some(Opcode::RegisterName) => { + let buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) }; + let registration = buffer.to_original::().unwrap(); + context_mgr.register_name(registration.name.to_str(), ®istration.auth_token); + } Some(Opcode::Quit) => break, None => {log::error!("unhandled message {:?}", msg);} } diff --git a/services/gam/src/tokens.rs b/services/gam/src/tokens.rs index ec046cade..d4c917570 100644 --- a/services/gam/src/tokens.rs +++ b/services/gam/src/tokens.rs @@ -1,4 +1,3 @@ -#[cfg(not(feature = "app_loader"))] use gam::{EXPECTED_BOOT_CONTEXTS, EXPECTED_APP_CONTEXTS}; /* @@ -19,21 +18,20 @@ pub(crate) struct NamedToken { } pub(crate) struct TokenManager { tokens: Vec::, + extra_names: Vec, trng: trng::Trng, } impl<'a> TokenManager { pub(crate) fn new(xns: &xous_names::XousNames) -> TokenManager { TokenManager { tokens: Vec::new(), + extra_names: Vec::new(), trng: trng::Trng::new(&xns).unwrap(), } } /// checks to see if all the slots have been occupied. We can't allow untrusted code to run until all slots have checked in pub(crate) fn allow_untrusted_code(&self) -> bool { - #[cfg(feature = "app_loader")] - return true; - #[cfg(not(feature = "app_loader"))] - if self.tokens.len() == (EXPECTED_BOOT_CONTEXTS.len() + EXPECTED_APP_CONTEXTS.len()) { + if self.tokens.len() == (EXPECTED_BOOT_CONTEXTS.len() + EXPECTED_APP_CONTEXTS.len() + self.extra_names.len()) { true } else { // throw a bone to the dev who has to debug this error. This typically only triggers after a major @@ -47,21 +45,21 @@ impl<'a> TokenManager { } pub(crate) fn claim_token(&mut self, name: &str) -> Option<[u32; 4]> { log::trace!("claiming token {}", name); - // first check if the name is valid if the app loader isn't enabled - #[cfg(not(feature = "app_loader"))] - { - let mut found = false; - if EXPECTED_BOOT_CONTEXTS.iter().find(|&&context| context == name).is_some() { - found = true; - } - if EXPECTED_APP_CONTEXTS.iter().find(|&&context| context == name).is_some() { - found = true; - } - if !found { - log::error!("Server {} is not pre-registered in gam/lib.rs/EXPECTED_BOOT_CONTEXTS or apps.rs/EXPECTED_APP_CONTEXTS. Did you forget to register it?", name); - return None - } + // first check if the name is valid + let mut found = false; + if EXPECTED_BOOT_CONTEXTS.iter().find(|&&context| context == name).is_some() { + found = true; + } + if EXPECTED_APP_CONTEXTS.iter().find(|&&context| context == name).is_some() { + found = true; + } + if self.extra_names.iter().find(|&context| context == name).is_some() { + found = true; } + if !found { + log::error!("Server {} is not pre-registered in gam/lib.rs/EXPECTED_BOOT_CONTEXTS or apps.rs/EXPECTED_APP_CONTEXTS. Did you forget to register it?", name); + return None + } // now check if it hasn't already been registered if self.tokens.iter().find(|&namedtoken| namedtoken.name == name).is_some() { log::error!("Attempt to re-register a UX context: {}", name); @@ -97,4 +95,16 @@ impl<'a> TokenManager { } None } + /// Register a new name that can then claim a token. Note that only pre-registered applications are allowed to do this. + pub(crate) fn register_name(&mut self, name: &str, auth_token: &[u32; 4]) { + if let Some(registrant) = self.lookup_name(auth_token) { + if EXPECTED_BOOT_CONTEXTS.iter().find(|&&context| context == registrant).is_some() || EXPECTED_APP_CONTEXTS.iter().find(|&&context| context == registrant).is_some() { + self.extra_names.push(name.to_string()); + } else { + log::error!("`{}' does not have permission to register a new name because it is not pre-registered", registrant); + } + } else { + log::error!("Token {:?} does not correspond with a name", auth_token); + } + } }