feat(storage): scoped grants (subtree, ro/rw), narrow-only, release revokes all holders; IPC KEEP_DELEGATE opt-in; shell cd/pwd, programs get ro cwd

This commit is contained in:
2026-10-27 20:20:34 +01:00
parent c603a578c0
commit 1fc5a54f06
38 changed files with 1237 additions and 170 deletions

View File

@@ -78,10 +78,16 @@ 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 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 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 given = syscall::delegate(copy, child, perms(&[Permission::Execute, Permission::Delegate]));
syscall::drop_cap(copy);
given.ok_or("cannot give an endpoint")?;

View File

@@ -26,8 +26,12 @@ pub fn run() -> ! {
// Storage waits for its disk before serving, so this comes first.
let found = devices::discover();
let disk = libkos::device::give_device(STORAGE_EP, found.disk).is_ok() && found.disk.mmio.is_some();
libkos::println!("init: disk: {}", if disk { "handed to its driver" } else { "none" });
let disk =
libkos::device::give_device(STORAGE_EP, found.disk).is_ok() && found.disk.mmio.is_some();
libkos::println!(
"init: disk: {}",
if disk { "handed to its driver" } else { "none" }
);
let Ok(mut storage) = Storage::attach(STORAGE_EP, STORAGE_BUF_VA) else {
libkos::println!("init: cannot reach storage, nothing to load");
@@ -53,7 +57,10 @@ pub fn run() -> ! {
// The test image carries the SMP self-test; it and the tests run
// instead of the desktop, and the last one halts the machine.
let (storage, scratch) = launcher.storage();
if storage.open(b"smptest.elf").is_ok_and(|h| storage.close(h).is_ok()) {
if storage
.open(b"smptest.elf")
.is_ok_and(|h| storage.close(h).is_ok())
{
libkos::println!("init: running the SMP self-test");
selftest::run(storage, scratch);
launch_all(&mut launcher, manifest::TESTS);
@@ -83,9 +90,15 @@ fn give_storage_the_log() {
let Some(log) = libkos::start::log() else {
return;
};
let call_only = PermissionSet::empty().with(Permission::Execute).with(Permission::Delegate);
let call_only = PermissionSet::empty()
.with(Permission::Execute)
.with(Permission::Delegate);
if let Ok(copy) = syscall::mint(log, Badge::NONE, call_only) {
let _ = syscall::call(STORAGE_EP, [types::storage::op::SET_LOG, 0, 0, 0], Some(copy));
let _ = syscall::call(
STORAGE_EP,
[types::storage::op::SET_LOG, 0, 0, 0],
Some(copy.into()),
);
syscall::drop_cap(copy);
}
}

View File

@@ -165,9 +165,12 @@ impl Server for Launcher<'_> {
Reply(refused(reply::ERROR).0)
}
fn handle_call(&mut self, badge: usize, words: [usize; 4], _cap: Option<CapSlot>) -> ([usize; 4], Option<CapSlot>) {
fn handle_call(&mut self, badge: usize, words: [usize; 4], _cap: Option<CapSlot>) -> ([usize; 4], Option<libkos::syscall::Give>) {
match Request::decode(words) {
Some(r) => self.spawn(badge, &r),
Some(r) => {
let (reply, process) = self.spawn(badge, &r);
(reply, process.map(Into::into))
}
None => ([MALFORMED, 0, 0, 0], None),
}
}