feat(apps): permission manager equips apps (manifest+consent+decisions in /system), launches via init w/ file grant; shell unprivileged (/home); install/apps/allow/revoke; revoke stops running app; app-image tool; counter app

This commit is contained in:
2026-10-27 22:56:44 +01:00
parent 9bc31a9bbe
commit 90e11eb2e8
51 changed files with 1766 additions and 644 deletions

View File

@@ -44,9 +44,9 @@ 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")?;
// Storage was started by boot, before init; programs may use it too.
let mut served = [None; MAX_SERVED];
served[0] = Some(("storage", crate::STORAGE_EP));
// Storage, started by boot, is not among them: it is reached
// through grants (a program's `storage` scope).
let served = [None; MAX_SERVED];
Ok(Self { storage, scratch, devices, served, next_badge: 1, spawn_ep, deaths, spawner: Spawner::new() })
}
@@ -78,20 +78,21 @@ impl<'a> Launcher<'a> {
// and take other clients' requests.
for name in p.uses {
let ep = self.endpoint(name).ok_or("needs a server that is not running")?;
let copy = match *name {
// Storage issues its own badges, each naming a scope.
"storage" => self.storage.grant(b"", true).map_err(|_| "storage refused a grant")?,
_ => {
let badge = Badge::new(self.next_badge);
self.next_badge += 1;
syscall::mint(ep, badge, perms(&[Permission::Execute, Permission::Delegate]))
.map_err(|_| "cannot mint 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")?;
}
// Storage issues its own badges, each naming a scope.
if let Some(scope) = p.storage {
let grant = self.storage.grant(scope.path, scope.write).map_err(|_| "storage refused a grant")?;
let given = syscall::delegate(grant, child, perms(&[Permission::Execute, Permission::Delegate]));
syscall::drop_cap(grant);
given.ok_or("cannot give storage")?;
}
if let Some(allowance) = p.spawns {
self.give_spawn(child, allowance)?;
}
@@ -126,7 +127,8 @@ impl<'a> Launcher<'a> {
let badge: Badge = self.spawner.add_client(allowance).ok_or("too many spawn clients")?;
let minted = perms(&[Permission::Execute, Permission::Delegate]);
let copy = syscall::mint(self.spawn_ep, badge, minted).map_err(|_| "cannot mint")?;
let given = syscall::delegate(copy, child, perms(&[Permission::Execute]));
// Delegate, to send the program file's grant with each request.
let given = syscall::delegate(copy, child, perms(&[Permission::Execute, Permission::Delegate]));
syscall::drop_cap(copy);
given.map(|_| ()).ok_or("cannot give the spawn endpoint")
}