Allow registration of GAM names

This allows `app-loader' to register new names (which are then used by
the loaded apps to claim tokens). At the moment this is restricted to
apps that are pre-registered, i.e. included in the image.
This commit is contained in:
Vihaan Jim 2023-08-04 21:32:35 -04:00
parent 9eeed0d284
commit 1e645a4b94
7 changed files with 58 additions and 21 deletions

View file

@ -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();

View file

@ -52,4 +52,3 @@ tts = []
# default = ["debugprint"] # "debugprint"
default = []
ditherpunk = []
app_loader = []

View file

@ -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<u32>,
}
#[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

View file

@ -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()
}

View file

@ -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,

View file

@ -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::<NameRegistration, _>().unwrap();
context_mgr.register_name(registration.name.to_str(), &registration.auth_token);
}
Some(Opcode::Quit) => break,
None => {log::error!("unhandled message {:?}", msg);}
}

View file

@ -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::<NamedToken>,
extra_names: Vec<String>,
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);
}
}
}