feat(kernel): shared ABI decoder+proofs, no-panic gate, syscall storm, kani on shrunk kernel

This commit is contained in:
2026-10-26 23:44:09 +01:00
parent 154599e3af
commit 130a82f50d
41 changed files with 1583 additions and 404 deletions

View File

@@ -1,5 +1,20 @@
#![no_std]
// A kernel panic takes the whole system down, so kernel code may not
// contain any way to panic. Tests and proofs are exempt.
#![cfg_attr(
not(any(test, kani)),
deny(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::unreachable,
clippy::todo,
clippy::unimplemented,
clippy::indexing_slicing
)
)]
pub mod abi;
mod captree;
pub mod interrupt;
mod memory;
@@ -136,11 +151,11 @@ impl<P: Platform> Kernel<P> {
}
pub fn pending_result(&self, thread: ThreadId) -> Option<&SyscallResult> {
self.pending_results[thread.raw() as usize].as_ref()
self.pending_results.get(thread.raw() as usize)?.as_ref()
}
pub fn take_pending_result(&mut self, thread: ThreadId) -> Option<SyscallResult> {
self.pending_results[thread.raw() as usize].take()
self.pending_results.get_mut(thread.raw() as usize)?.take()
}
pub fn set_thread_running(
@@ -268,10 +283,8 @@ impl<P: Platform> Kernel<P> {
{
Ok(p) => {
let mut ids = [None; MAX_THREADS_PER_PROCESS];
for (i, tid) in p.thread_ids().enumerate() {
if i < MAX_THREADS_PER_PROCESS {
ids[i] = Some(tid);
}
for (slot, tid) in ids.iter_mut().zip(p.thread_ids()) {
*slot = Some(tid);
}
ids
}
@@ -292,19 +305,19 @@ impl<P: Platform> Kernel<P> {
for tid in thread_ids.iter().flatten() {
self.endpoints.remove_thread_from_all(*tid);
self.notifications.remove_thread_from_all(*tid);
let ipc = core::mem::take(&mut self.ipc[tid.raw() as usize]);
let ipc = self.ipc_mut(*tid).map(core::mem::take).unwrap_or_default();
if let Some(caller) = ipc.reply_to {
self.release_caller(caller);
}
self.scheduler.remove(*tid);
self.pending_results[tid.raw() as usize] = None;
self.set_pending_result(*tid, None);
let _ = self.threads.destroy(*tid);
}
}
/// Destroys every endpoint `owner` created, waking anyone blocked on
/// them with an error instead of leaving them blocked forever.
fn destroy_endpoints_owned_by(&mut self, owner: ProcessId) {
pub(crate) fn destroy_endpoints_owned_by(&mut self, owner: ProcessId) {
let mut owned = [None; domain::endpoint::MAX_ENDPOINTS];
for (slot, id) in owned.iter_mut().zip(self.endpoints.ids_owned_by(owner)) {
*slot = Some(id);
@@ -330,8 +343,10 @@ impl<P: Platform> Kernel<P> {
let Some(mut n) = self.notifications.destroy(id) else {
continue;
};
if let Some(bound) = n.bound() {
self.ipc[bound.raw() as usize].bound = None;
if let Some(bound) = n.bound()
&& let Some(s) = self.ipc_mut(bound)
{
s.bound = None;
}
while let Some(tid) = n.pop_waiter() {
self.wake_with_error(tid, KernelError::NoSuchObject);
@@ -342,7 +357,9 @@ impl<P: Platform> Kernel<P> {
/// Makes a blocked thread runnable with `error` as its syscall result,
/// dropping whatever it was about to send.
fn wake_with_error(&mut self, tid: ThreadId, error: KernelError) {
self.ipc[tid.raw() as usize].outgoing = None;
if let Some(s) = self.ipc_mut(tid) {
s.outgoing = None;
}
self.wake(tid, SyscallResult::Error(error));
}