feat(display): input routed via display server to focused app; input Subscribe; uses caps badged + Delegate

This commit is contained in:
2026-10-27 16:38:16 +01:00
parent 64ec5df379
commit 2845d190f0
18 changed files with 286 additions and 26 deletions

View File

@@ -27,6 +27,8 @@ pub(crate) struct Launcher<'a> {
devices: Devices,
/// The endpoint of every server started so far, by name.
served: [Option<(&'static str, CapSlot)>; MAX_SERVED],
/// The badge on the next client's endpoint copy (0 is init's own).
next_badge: usize,
/// Init's own endpoint, for the spawn service.
pub(crate) spawn_ep: CapSlot,
/// Bound to init's thread: spawned children's deaths, a bit each.
@@ -42,7 +44,7 @@ impl<'a> Launcher<'a> {
) -> Result<Self, &'static str> {
let spawn_ep = syscall::create_endpoint().ok_or("no spawn endpoint")?;
let deaths = syscall::create_notification().map_err(|_| "no death notification")?;
Ok(Self { storage, scratch, devices, served: [None; MAX_SERVED], spawn_ep, deaths, spawner: Spawner::new() })
Ok(Self { storage, scratch, devices, served: [None; MAX_SERVED], next_badge: 1, spawn_ep, deaths, spawner: Spawner::new() })
}
pub(crate) fn storage(&mut self) -> (&mut Storage, &mut [u8]) {
@@ -68,11 +70,18 @@ impl<'a> Launcher<'a> {
}
false => None,
};
// A client only calls: Execute, never Read, so it cannot pose as the
// server and take other clients' requests.
// A client calls (Execute) and may send capabilities through it and
// pass it on (Delegate); never Read, so it cannot pose as the server
// and take other clients' requests.
for name in p.uses {
let ep = self.endpoint(name).ok_or("needs a server that is not running")?;
syscall::delegate(ep, child, perms(&[Permission::Execute])).ok_or("cannot give an endpoint")?;
let badge = Badge::new(self.next_badge);
self.next_badge += 1;
let copy = syscall::mint(ep, badge, perms(&[Permission::Execute, Permission::Delegate]))
.map_err(|_| "cannot mint an endpoint")?;
let given = syscall::delegate(copy, child, perms(&[Permission::Execute, Permission::Delegate]));
syscall::drop_cap(copy);
given.ok_or("cannot give an endpoint")?;
}
if let Some(allowance) = p.spawns {
self.give_spawn(child, allowance)?;