T-026 — current-task capability table + per-task window in syscall_entry (B6 gate #3)#40
Conversation
…ings + accessors (gate #3) Adds two scheduler parallel arrays (mirroring task_address_space_handles): task_cap_tables (Option<*mut CapabilityTable> — raw ptr, BSP-owned, ADR-0021 bridge; the H1 review fix) + task_user_windows (Option<UserAccessWindow> = [entry_va, stack_top_va), built from add_user_task's existing user_entry/user_sp). add_user_task gains a cap_table param and records both bindings. New pub accessors current_user_table() / current_address_space_handle() / current_user_window() resolve self.current -> slot -> the arrays, returning None (the fail-closed signal) for no-current / unbound slots. The raw ptr makes Scheduler !Send/!Sync; it only ever lives inside the BSP's unconditionally-Sync StaticCell, reached via the *mut Scheduler bridge — no Send/Sync bound broken. No consumer yet (the syscall_entry rewire + fail-closed dispatch is step B). Refs: T-026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… test + AF-check audit note Post-merge security review of gate #1 (PR #39) verdict: confused-deputy closed, all-or-nothing clean, lock-shut decoder, read-only translate, fail-closed — all verified. Two minor findings actioned: (BULGU-1) add copy_from_user_block_mapped_page_faults — the probe maps every translate error (incl. BlockMapped) to FaultAddress, but only the NotMapped arm had a copy-path test; uses the existing BlockMappedMmu decorator. (BULGU-3) note in the UNSAFE-2026-0025 amendment that the AF=0->NotMapped filter (d0e5a17) is a pure read-only guard (no write site / frame alloc / new invariant). Skipped (BULGU-2): Mmu::map allowing DEVICE|USER is not a defect here — the copy-time USER check is correct; the proper fix is at map-time (cap_map rejecting DEVICE|USER), a future B6+ item, and no v1 leaf is DEVICE|USER. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…late consumers (T-026 gate #3 prep) syscall_entry (gate #3) needs the running task's concrete &M::AddressSpace to pass to the gate-#1 Mmu::translate copy-user path. inner() is &self (shared) so it grants no mutation — all map/unmap still flow through the cap-gated wrappers via inner_mut; exposing the immutable view bypasses no capability check. Refs: T-026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ng + fail-closed (B6 gate #3) syscall_entry sources the running EL0 task's capability table + address space + user-access window from SCHED.current (scheduler accessors landed in step A), failing closed to the empty FAILCLOSED_TABLE + empty window when no task is current. AddressSpace::inner() widened to pub (read-only) so the BSP can pass the task's &QemuVirtAddressSpace to gate-#1 Mmu::translate. The H2 control-plane fail-closed lands in the dispatcher via SyscallContext.has_current_task (host-testable; the BSP can't construct the #[non_exhaustive] SyscallError): task_yield/task_exit -> InvalidHandle when no task is current. The +0x200 smoke is re-sequenced after SCHED init (current=None) and now demonstrates gate-#3 fail-closed (console_write -> InvalidHandle 0x102); SYSCALL_STUB_TABLE retired -> the empty FAILCLOSED_TABLE. Closes the last T-021 carry-forward gate (#1 T-025 + #2 T-023 + #3 T-026 all done). Gates: fmt; host+kernel clippy -D warnings; host tests kernel 257 / hal 46 / test-hal 58 / 3 doc (new: current_accessors_resolve_running_task_bindings_or_none, task_{yield,exit}_with_no_current_task_fails_closed); kernel build; QEMU smoke PASS (2 SVC, clean ERET, zero new fault class); Miri 0 UB. Mandatory UNSAFE-2026-0014 Amendment (cap-table deref) + UNSAFE-2026-0029 Amendment (statics + smoke re-sequence). Refs: T-026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewer's GuideRewires syscall_entry to source capability tables, address spaces, and per-task user-access windows from the scheduler’s current EL0 task instead of a fixed kernel stub table, introduces per-task cap-table and window bindings in the scheduler, adds dispatcher-level fail-closed handling for control-plane syscalls when no task is current, retires the stub syscall table in favor of an empty fail-closed table, and updates tests, unsafe audit entries, and documentation to reflect gate #3 closure. Sequence diagram for syscall_entry sourcing current-task capabilities and failing closedsequenceDiagram
participant Task as EL0_or_stub_caller
participant SE as syscall_entry
participant S as Scheduler
participant ASArena as AS_ARENA
participant FCT as FAILCLOSED_TABLE
participant BOOTAS as BOOTSTRAP_AS
participant D as dispatch
Task->>SE: SVC #0
SE->>S: current_user_table()
SE->>S: current_address_space_handle()
SE->>S: current_user_window()
alt current task bound
SE->>ASEntry: get_address_space(AS_ARENA, handle)
ASEntry-->>SE: Some(AddressSpace) or None
alt AddressSpace found
SE->>D: dispatch(SyscallContext {\n caller_table: &mut *table_ptr,\n user_window: window,\n task_as: as.inner(),\n has_current_task: true\n})
else AddressSpace missing
SE->>BOOTAS: assume_init_ref()
SE->>D: dispatch(SyscallContext {\n caller_table: &mut *table_ptr,\n user_window: UserAccessWindow::empty(),\n task_as: &*BOOTSTRAP_AS,\n has_current_task: true\n})
end
else no current task
SE->>FCT: assume_init_mut()
SE->>BOOTAS: assume_init_ref()
SE->>D: dispatch(SyscallContext {\n caller_table: &mut FAILCLOSED_TABLE,\n user_window: UserAccessWindow::empty(),\n task_as: &*BOOTSTRAP_AS,\n has_current_task: false\n})
end
D-->>SE: SyscallEffect
SE-->>Task: resume / reschedule / terminate based on SyscallEffect
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR implements B6 gate ChangesGate
Sequence Diagram(s)sequenceDiagram
Participant EL0 as EL0 (user)
Participant EL1 as syscall_entry (EL1)
Participant Sched as Scheduler
Participant Dispatch as dispatch
Participant Table as FAILCLOSED_TABLE / CapabilityTable
EL0->>EL1: SVC (syscall)
EL1->>Sched: read current_user_table(), current_user_window(), current_address_space_handle()
Sched-->>EL1: Option<cap_table>, Option<window>, Option<AS>
EL1->>Table: choose FAILCLOSED_TABLE or deref cap_table
EL1->>Dispatch: dispatch(SyscallContext{has_current_task})
Dispatch-->>EL1: SyscallEffect (Resume/Reschedule/Terminate / InvalidHandle)
EL1-->>EL0: return status in x0
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request implements the T-026 (gate #3) fail-closed fallback mechanism, transitioning the syscall entry path to resolve capability tables, address spaces, and user-access windows dynamically from the scheduler's current task instead of using a static stub table. When no task is running, the system fails closed using an empty fallback table and window, and control-plane syscalls are rejected. However, a critical security issue was identified: initializing the fallback FAILCLOSED_TABLE inside the diagnostic syscall_boundary_smoke function couples a core security mechanism to a test. If the smoke test is disabled or removed, the table will remain uninitialized, leading to undefined behavior during a fail-closed syscall. This initialization should be moved to the core kernel setup.
| // SAFETY: `FAILCLOSED_TABLE` lives in `.bss`; this is its single write, | ||
| // before any `SVC` issues. Audit: UNSAFE-2026-0010 (StaticCell pattern). | ||
| unsafe { | ||
| (*FAILCLOSED_TABLE.0.get()).write(CapabilityTable::new()); | ||
| } |
There was a problem hiding this comment.
Initializing FAILCLOSED_TABLE inside syscall_boundary_smoke couples a critical kernel security fallback mechanism to a diagnostic smoke test. If syscall_boundary_smoke is ever disabled, bypassed, or removed in production, FAILCLOSED_TABLE will remain uninitialized, leading to undefined behavior (reading uninitialized memory via assume_init_mut()) on any fail-closed syscall.
FAILCLOSED_TABLE should be initialized as part of the core kernel/BSP setup in kernel_main_high alongside other system structures (like SCHED and EP_ARENA), rather than inside a smoke test.
There was a problem hiding this comment.
Fixed in f6bc9db. FAILCLOSED_TABLE is now initialised in core kernel_main_high setup (alongside EP_ARENA/IPC_QUEUES), not inside syscall_boundary_smoke, with an explicit ordering invariant. The security fallback is now live independent of whether the diagnostic smoke runs — closing exactly the "smoke removed → uninitialised .bss read via assume_init_mut()" UB you flagged. Good catch, thank you.
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The logic in
syscall_entrythat pullscurrent_user_table/current_address_space_handle/current_user_windowand wires up the fail-closed defaults is getting dense; consider factoring that into a small helper that returns{ caller_table, task_as, user_window, has_current_task }so the unsafe deref + invariants are localized and easier to audit. has_current_taskis derived fromcurrent_user_table().is_some(), which effectively equates "running EL0 task" with "has a cap table"; if you ever introduce task types that should be allowed totask_yield/task_exitwithout a cap table, this will silently treat them as "no current task"—it may be worth basing this flag on an explicit "is EL0"/"is schedulable" property instead of the cap-table binding.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The logic in `syscall_entry` that pulls `current_user_table` / `current_address_space_handle` / `current_user_window` and wires up the fail-closed defaults is getting dense; consider factoring that into a small helper that returns `{ caller_table, task_as, user_window, has_current_task }` so the unsafe deref + invariants are localized and easier to audit.
- `has_current_task` is derived from `current_user_table().is_some()`, which effectively equates "running EL0 task" with "has a cap table"; if you ever introduce task types that should be allowed to `task_yield`/`task_exit` without a cap table, this will silently treat them as "no current task"—it may be worth basing this flag on an explicit "is EL0"/"is schedulable" property instead of the cap-table binding.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bsp-qemu-virt/src/main.rs (1)
735-795:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAssert the expected fail-closed results.
Line 794 reports success unconditionally. If either
SVCstarts returning the wrong status, this smoke still printsok, so it won’t catch a gate#3regression.Suggested fix
unsafe { core::arch::asm!( "svc `#0`", in("x8") 0u64, out("x0") bad_status, out("x1") _, out("x2") _, out("x3") _, out("x4") _, out("x5") _, out("x6") _, out("x7") _, ); } + + assert_eq!( + status, 0x102, + "syscall smoke: console_write without a current task must fail closed with InvalidHandle", + ); + assert_eq!( + bad_status, 0x1, + "syscall smoke: reserved syscall number must return BadSyscallNumber", + ); let mut w = FmtWriter(console); let _ = writeln!( w, "tyrne: syscall smoke ok (gate `#3` fail-closed — no current task: console_write status={status:`#x`}; bad-number status={bad_status:`#x`})"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bsp-qemu-virt/src/main.rs` around lines 735 - 795, The test prints "ok" unconditionally; update syscall_boundary_smoke to assert the SVC results instead of always reporting success: after the first SVC compare status against the expected fail-closed error constant (the InvalidHandle/appropriate SyscallError value used by the dispatcher) and fail/log/panic if it differs, and after the second SVC compare bad_status against the SyscallError::BadSyscallNumber value and fail/log/panic if it differs; use the existing local variables status and bad_status and keep the final writeln only after both checks pass so the message truthfully reflects success.
🧹 Nitpick comments (1)
kernel/src/sched/mod.rs (1)
444-453: ⚡ Quick winAdd a debug-time null check for
cap_table.
add_user_taskstorescap_tableunconditionally, butsyscall_entrylater treats anySome(table_ptr)as dereferenceable. A null pointer here becomes “current task present” plus immediate UB on the first syscall.Suggested change
pub unsafe fn add_user_task( &mut self, cpu: &C, handle: TaskHandle, address_space_handle: AddressSpaceHandle, user_entry: usize, user_sp: usize, kernel_stack_top: *mut u8, cap_table: *mut CapabilityTable, ) -> Result<(), SchedError> { + debug_assert!( + !cap_table.is_null(), + "add_user_task: cap_table must be non-null", + ); let idx = handle.slot().index() as usize;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kernel/src/sched/mod.rs` around lines 444 - 453, In add_user_task, add a debug-time null-check for the cap_table pointer (e.g. debug_assert!(!cap_table.is_null(), "cap_table is null in add_user_task")) and also defensively handle a null pointer when storing it so syscall_entry won't treat a null as a valid dereferenceable pointer; either return an Err(SchedError::...) on null or store None instead of Some(cap_table) (update the field usage in syscall_entry to accept Option<*mut CapabilityTable> accordingly). Ensure references to add_user_task and syscall_entry are updated so the runtime never unconditionally treats a null cap_table as dereferenceable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bsp-qemu-virt/src/syscall.rs`:
- Around line 165-194: The syscall context currently mixes live and fallback
pieces; change the logic so the "current-task binding" is all-or-nothing:
compute a single boolean (e.g., has_full_binding) that is true only if
current_table.is_some(), current_window.is_some(), and the AS lookup (the match
using current_as -> tyrne_kernel::mm::get_address_space(arena, h)) succeeds; if
has_full_binding is false, set caller_table to FAILCLOSED_TABLE
(assume_init_mut), user_window to UserAccessWindow::empty(), task_as to
BOOTSTRAP_AS (assume_init_ref), and has_current_task to false, otherwise use the
existing live values (caller_table from current_table, user_window from
current_window.unwrap(), task_as from the successful AS lookup, and
has_current_task = true). Update references around
current_table/current_window/current_as, task_as, caller_table, and
has_current_task accordingly.
In `@kernel/src/syscall/user_access.rs`:
- Around line 508-526: The test fails to compile because the call to
BlockMappedMmu::create_address_space is missing a closing parenthesis; update
the test so the unsafe block that assigns `as_` properly closes the
create_address_space(...) call and the unsafe block (i.e., ensure the expression
`unsafe {
mmu.create_address_space(PhysFrame::from_aligned(PhysAddr(0x1000)).unwrap()) }`
is syntactically complete), referencing the `BlockMappedMmu`,
`create_address_space`, `PhysFrame::from_aligned`, and local variable `as_`.
---
Outside diff comments:
In `@bsp-qemu-virt/src/main.rs`:
- Around line 735-795: The test prints "ok" unconditionally; update
syscall_boundary_smoke to assert the SVC results instead of always reporting
success: after the first SVC compare status against the expected fail-closed
error constant (the InvalidHandle/appropriate SyscallError value used by the
dispatcher) and fail/log/panic if it differs, and after the second SVC compare
bad_status against the SyscallError::BadSyscallNumber value and fail/log/panic
if it differs; use the existing local variables status and bad_status and keep
the final writeln only after both checks pass so the message truthfully reflects
success.
---
Nitpick comments:
In `@kernel/src/sched/mod.rs`:
- Around line 444-453: In add_user_task, add a debug-time null-check for the
cap_table pointer (e.g. debug_assert!(!cap_table.is_null(), "cap_table is null
in add_user_task")) and also defensively handle a null pointer when storing it
so syscall_entry won't treat a null as a valid dereferenceable pointer; either
return an Err(SchedError::...) on null or store None instead of Some(cap_table)
(update the field usage in syscall_entry to accept Option<*mut CapabilityTable>
accordingly). Ensure references to add_user_task and syscall_entry are updated
so the runtime never unconditionally treats a null cap_table as dereferenceable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 09ab1e28-c5aa-4ca8-9b00-d277ac6d60e7
📒 Files selected for processing (10)
bsp-qemu-virt/src/main.rsbsp-qemu-virt/src/syscall.rsdocs/analysis/tasks/phase-b/T-026-current-task-cap-table.mddocs/audits/unsafe-log.mddocs/roadmap/current.mddocs/roadmap/phases/phase-b.mdkernel/src/mm/address_space.rskernel/src/sched/mod.rskernel/src/syscall/dispatch.rskernel/src/syscall/user_access.rs
…ILCLOSED in core setup + smoke asserts + null guard Addresses the PR #40 review (4 valid fixes; 2 findings skipped with reason): - syscall_entry: fold has_current_task into the same all-or-nothing match as the data-plane triple (table + user window + generation-checked AS). An incomplete running-task binding now also sets has_current_task=false, so the control-plane syscalls (task_yield/task_exit, which consult no capability) are rejected too — not just the data-plane. The whole caller context is all-or-nothing fail-closed. - main.rs: relocate FAILCLOSED_TABLE init from syscall_boundary_smoke into core kernel_main_high setup (alongside EP_ARENA/IPC_QUEUES), with an explicit ordering invariant, so the security fallback is live independent of whether the diagnostic smoke runs (removes a 'smoke removed -> uninit .bss UB' footgun). - main.rs: syscall_boundary_smoke now ASSERTS both SVC statuses != OK_STATUS before printing (a fail-closed regression would over-grant and report OK, panicking the boot before 'all tasks complete') instead of printing 'ok' unconditionally. - sched::add_user_task: debug_assert!(!cap_table.is_null()) + defensive (!cap_table.is_null()).then_some(cap_table) store, so a # Safety-contract violation degrades to None -> fail-closed instead of a Some(null) deref. - dispatch.rs: refresh the SyscallContext.has_current_task doc to the all-or-nothing semantics. Skipped: (a) 'BlockMapped test missing paren / won't compile' — the test compiles and passed; (b) 'base has_current_task on an explicit is-EL0 property' — in v1 only EL0 tasks (which always have a cap table) issue syscalls, so the equivalence holds (forward-flagged). Adversarially verified before commit: a 5-lens review workflow (all-or-nothing correctness, init-ordering, null-store, smoke-assert, audit-accuracy) found no real issues — the all-or-nothing lens cleared all 8 binding-state combinations. UNSAFE-2026-0014 + 0029 review-round amendments. Gates: fmt; host+kernel clippy -D warnings; host tests kernel 257 / hal 46 / test-hal 58 / 3 doc; kernel build; QEMU smoke PASS (asserts hold: console_write 0x102, bad-number 0x1; 2 SVC, clean ERET, zero new fault); Miri 0 UB (kernel 257). Refs: T-026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review-round resolution (f6bc9db)Thanks all. Verified each finding against the current tree; 4 fixed, 2 skipped with reason, plus 2 doc-accuracy nits closed. Fixed
Skipped (with reason)
On the "factor the binding into a helper" note (sourcery): the single all-or-nothing Verification: before committing I ran an adversarial 5-lens review pass (all-or-nothing correctness, init-ordering, null-store chain, smoke-assert soundness, audit accuracy) — no real issues; the all-or-nothing lens cleared all 8 binding-state combinations. Gates: fmt; host + kernel clippy |
…closed on both planes Closes the one 'Kısmi' (partial) item from the review verification: there was no host test directly modelling the context the BSP syscall_entry produces on an incomplete running-task binding (empty FAILCLOSED_TABLE + empty window + has_current_task=false). The BSP match that assembles it is no_std/no_main and not host-testable directly, but the dispatcher's handling of that exact context is — and the prior suite only covered the planes separately (console_write with has_current_task=true; task_yield with has_current_task=false), never the combined fail-closed context. The new test builds that exact context once and asserts BOTH planes fail closed in it: data-plane console_write -> InvalidHandle (no output, via the empty table) and control-plane task_yield -> InvalidHandle (via the has_current_task gate, not Reschedule). debug-gated (console_write number 5 is debug-only). Gates: fmt; host + kernel clippy -D warnings; kernel tests 258 (+1); Miri 0 UB on the new test. Refs: T-026 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-026 — current-task capability table + per-task window in
syscall_entry(B6 gate #3)Closes the last T-021 carry-forward gate — gate #3. With gate #1 (T-025) + gate #2 (T-023) already merged, all three are now closed, so the B6 wire-up can run a real EL0 task. No new ADR (rides ADR-0030 §step-7 + ADR-0021 + ADR-0014).
What it does
syscall_entryno longer resolves against a fixed kernel-stub table + the whole-RAM window. It sources the running EL0 task's own capability table, address space, and user-access window from the scheduler's current task, and fails closed when there is none:kernel/src/sched/mod.rs): two parallel arrays mirroringtask_address_space_handles—task_cap_tables: [Option<*mut CapabilityTable>; N](raw ptr, BSP-owned, ADR-0021 bridge) +task_user_windows: [Option<UserAccessWindow>; N]([entry_va, stack_top_va)), both written byadd_user_task(newcap_tableparam). Newcurrent_user_table()/current_address_space_handle()/current_user_window()accessors returnNone(the fail-closed signal) for no-current / unbound slots. The raw ptr makesScheduler!Send/!Sync— absorbed by the BSP's unconditionally-SyncStaticCell<Scheduler>, reached via the ADR-0021*mut Schedulerbridge.syscall_entryrewire (bsp-qemu-virt/src/syscall.rs): sources table/AS/window fromSCHED.current; with no current task → the emptyFAILCLOSED_TABLE(every lookup →InvalidHandle) + an empty window + a never-dereferenced bootstrap-AS placeholder.AddressSpace::inner()widened topub(read-only — grants no mutation, so no cap-gate bypass) so the BSP can pass the task's&QemuVirtAddressSpaceto gate-Development #1Mmu::translate.kernel/src/syscall/dispatch.rs), not a BSP short-circuit — the BSP can't construct the#[non_exhaustive]SyscallError, and the dispatcher version is host-testable:SyscallContextgainshas_current_task: bool;task_yield/task_exit(which consult no capability, so the empty table can't guard them) →InvalidHandlewhen it isfalse.Smoke (maintainer chose: fail-closed demo)
The
+0x200stub smoke is re-sequenced afterSCHEDis published (soSCHED.currentisNone) and now demonstrates gate-#3 fail-closed:console_write→InvalidHandle(status0x102),bad-number→BadSyscallNumber; 2 SVC exceptions, cleanERET, zero new fault class.SYSCALL_STUB_TABLEretired → the emptyFAILCLOSED_TABLE. (The B5 cap-mint + greeting are superseded — a syscall with no running task being rejected is the security property worth showing; the real positive EL0+0x400round-trip is the wire-up.)Pre-implementation reviews (relayed, verified against the live tree)
Two reviews hardened the design before/early implementation — applied: H1 persist the per-task window in a scheduler array (the
LoadedImagespan was reachable nowhere); H2 control-plane fail-closed (above); M4 mandatory (not conditional) UNSAFE-2026-0014 amendment. This PR also carries a small T-025 gate-#1 follow-up (commit6cbb684): aBlockMappedcopy-path test + an AF-check audit note (2 valid; the DEVICE|USER finding forward-flagged tocap_map).Commit arc
54a1795task_cap_tables/task_user_windows+ accessors +add_user_taskparam6cbb68415a9d80AddressSpace::inner()→pub(read-only; gate-#3 prep)syscall_entryrewire + fail-closed + control-plane gate + smoke re-sequence + tests + audit amendments + docsGates (all green)
cargo fmt --all --check✅-D warnings✅current_accessors_resolve_running_task_bindings_or_none,task_{yield,exit}_with_no_current_task_fails_closed)cargo kernel-build✅all tasks complete; 2 SVC exceptions, cleanERET, zero new fault class; gate-Development #3 fail-closed shown ✅cargo +nightly miri test --workspace --exclude tyrne-bsp-qemu-virt— 0 UB ✅Audit
UNSAFE-2026-0014 Amendment (mandatory — the
syscall_entry&mut *table_ptrcap-table deref; second-reviewer required) + UNSAFE-2026-0029 Amendment (the syscall-arc statics change + smoke re-sequence). No newunsafeentries.Out of scope (follow-ups)
tyrne-user+userland/hello+ thecargo → objcopy → include_bytes!build pipeline (ADR-0029 §Build pipeline).+0x400wire-up smoke + B6 closure (Phase B retrospective).🤖 Generated with Claude Code
Summary by Sourcery
Wire syscall handling to use the scheduler’s current EL0 task context (capability table, address space, and user window) and make syscalls fail-closed when no task is running, completing gate #3 for the B6 EL0 wire-up.
Enhancements:
syscall_entryto derive caller capability table, address space, and user-access window from the current task, with an empty fail-closed table and window when no task is current, and makeAddressSpace::innerpublicly readable for MMU translation.has_current_taskguard sotask_yieldandtask_exitreject withInvalidHandlewhen no EL0 task is current, preserving control-plane fail-closed semantics.Documentation:
Tests:
Summary by CodeRabbit
Bug Fixes
Refactor
Documentation
Tests