Skip to content

docs(B5): closure trio — security + performance + business (close Milestone B5)#35

Merged
cemililik merged 6 commits into
mainfrom
sec-review-b5-syscall-boundary
May 29, 2026
Merged

docs(B5): closure trio — security + performance + business (close Milestone B5)#35
cemililik merged 6 commits into
mainfrom
sec-review-b5-syscall-boundary

Conversation

@cemililik
Copy link
Copy Markdown
Collaborator

@cemililik cemililik commented May 29, 2026

B5 closure trio — close Milestone B5 (Syscall boundary)

Docs-only. The B5 implementation (T-020 + T-021) already merged to main via #34 (f98e1af); this PR lands the closure trio that formally promotes Milestone B5 from implementation-complete to Closed, plus one B4-forward-flagged doc reconcile. No kernel changes — the kernel binary is byte-identical to f98e1af.

Commits

  • c424dcb security review — Approve, eight axes; the EL0→EL1 boundary is panic-free, capability-gated, copy-user-validated; UNSAFE-2026-0029/0030 policy-conformant (0029 second-reviewer-signed).
  • afeed10 security-model.md SMMUv3 reconcile — closes a B4 forward-flag: the two stale "QEMU virt has SMMUv3 / is the CI gate" claims now state the v1 GICv2/no-IOMMU reality and point at ADR-0036.
  • a5395b7 performance baseline — re-baseline; a same-host control (the B4 binary 3ab029f rebuilt + re-measured this session) proves the ~+2.9 ms p10/p50 delta vs B4 is a real one-time boot SVC-smoke cost, not host jitter (it corrected an initial mis-read of the noisier band; the B4 binary reproduced its own p50 across sessions).
  • 0b665db business retrospective + roadmap forward motion (current.md banner/Pathfinder → B6; phase-b.md §B5 → Closed; the mid-arc test-count drift 236/240 → live 339 reconciled).

Closing metrics (reproduced live at afeed10)

  • 339 host tests (43 hal + 240 kernel + 53 test-hal + 3 doc; +53 kernel) — cargo miri test --workspace --exclude tyrne-bsp-qemu-virt clean (0 UB, run locally — first closure to do so).
  • fmt / host-clippy / kernel-clippy / kernel-build clean.
  • Release ELF .text 34,648 / .rodata 4,856 / .bss 50,592 (~88.0 KiB, +4.8 % vs B4 — the smallest non-refactor .text growth in Phase B).
  • Release perf band p10/p50/p90 = 17.645 / 20.300 / 24.706 ms.
  • QEMU smoke clean to tyrne: all tasks complete; -d int,unimp,guest_errors = 712 (release) / 776 (debug) pre-existing PL011 warnings + 2 expected SVC exceptions (EL1→EL1, ESR 0x15/0x56000000 = SVC64, clean ERET), zero new fault class.
  • Audit log 30 entries (29 Active).

Reviews

Next

Milestone B6 (first userspace "hello", the Phase-B-closing milestone) opens on a fresh branch off this PR's merge. The openers: ADR-0033 (kernel-reachable-from-every-AS / high-half, so an EL0 task's SVC vector fetch translates), the deferred task_create_from_image bridge (LoadedImage → runnable TaskCap), and the three T-021 carry-forward gates (per-task console_write window + per-page user-VA translation; SP_EL1 init for the +0x400 entry; SYSCALL_STUB_TABLE → current-task table).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Published and indexed a B5 syscall-boundary security review (approved) and added related business-retrospective and performance-baseline/closure reports.
    • Updated roadmap, Phase B, and README to mark B5 closed and promote B6 as the next milestone.
    • Clarified architecture guidance (IOMMU expectations, high‑half/TTBR sequencing, and task-loader/B6 gating).
    • Minor project-status update (CLAUDE.md).

Review Change Stack

cemililik and others added 2 commits May 29, 2026 16:12
Standalone consolidated security pass over the B5 syscall boundary (T-020 IpcError
split + Capability/CapObject Debug redaction K3-9; T-021 EL0→EL1 SVC dispatch),
merged via PR #34 (f98e1af). Performed with a fresh 8-axis checklist after the
PR's three code-review rounds + the adversarial multi-agent pass.

Verdict: **Approve.** All eight applicable axes pass (cryptography N/A). The
dispatcher is panic-free on every register-supplied input; every object-naming
syscall is capability-gated before any effect (console_write on the new
debug-console cap, closing the ambient-authority slip caught before ADR Accept);
copy-from/to-user never dereferences an unvalidated user pointer, with the
soundness basis honestly recorded as the user/kernel disjointness invariant
(an empirical Miri probe disproved an earlier "overlap-tolerant" over-claim —
overlap is UB regardless of the copy primitive via the &mut/& borrow exclusivity);
T-020's Debug redaction closes the K3-9 secrets-leak path exactly where B5 first
creates a userspace-reachable log channel. Both new unsafe entries
(UNSAFE-2026-0029 trampoline asm, UNSAFE-2026-0030 copy-user) are policy-conformant;
0029 carries the required second-reviewer sign-off. Gates: host-test 240,
test --release green, miri --workspace clean (0 UB), QEMU +0x200 proxy round-trip
byte-stable with no new fault class.

B5 builds the boundary mechanism but the real EL0 +0x400 transition is B6; three
B6 carry-forward gates (per-task console_write window + per-page translation;
SP_EL1 init; SYSCALL_STUB_TABLE → current-task table) are tracked in phase-b.md
§B6. This pass can serve as the security leg of the eventual B5 closure trio
(business + performance legs deferred — "security review first").

Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0014
Security-Review: @cemililik (+ Claude Opus 4.8 agent)
Audit: UNSAFE-2026-0029, UNSAFE-2026-0030
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…0036 (B5 review finding)

The B5 syscall-boundary security review (this PR) re-surfaced the one finding
actionable outside a phase gate: security-model.md §threat-model #7 + §Open
questions still described QEMU `virt` as "launched with SMMUv3 and used in CI to
catch driver misbehaviour" — a live contradiction with Accepted ADR-0036 (QEMU
`virt` is GICv2 / no-IOMMU in v1; SMMUv3 is exposed only under an explicit
`iommu=smmuv3` launch Tyrne does not use). It was N/A as a v1 *defect* (no
bus-master driver exists, so the DMA boundary is inactive) but a stale doc claim,
forward-flagged since the 2026-05-28 B4 closure.

Reconciled conservatively: both sentences now state the v1 GICv2/no-IOMMU reality,
point at ADR-0036, and reframe the SMMU-in-CI gate as a future IOMMU-equipped-target
(Jetson Orin) item — preserving the model's IOMMU intent, correcting only the
stale QEMU-`virt`-has-SMMUv3 claim. The review doc's §8 + forward-flags are updated
to mark this RECONCILED (no longer carried forward). All other review forward-flags
are correctly phase-deferred (B6 carry-forward gates / Phase-E fault containment /
preemption-time ipc_send hardening / B5+ cap_map rights ADR) — no action now.

Refs: ADR-0013, ADR-0036
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 29, 2026

Reviewer's Guide

Documents the consolidated security review for the B5 syscall boundary (T-020 + T-021) and reconciles the security model docs with ADR-0036 regarding QEMU virt IOMMU/SMMU assumptions, adding a new detailed security-review artefact and extending the review index.

File-Level Changes

Change Details Files
Clarify the security model's treatment of peripheral DMA and IOMMU/SMMU policy for QEMU virt in light of ADR-0036.
  • Update threat-model entry for peripheral DMA to state that the v1 QEMU virt target is GICv2 with no IOMMU and does not provide an SMMUv3-enabled CI gate today
  • Revise the open-questions section on IOMMU/SMMU policy to clarify that an SMMU-driven CI gate is a future item for an IOMMU-equipped target and not a v1 QEMU virt capability
  • Reference ADR-0036 from both updated paragraphs to anchor the documented hardware reality
docs/architecture/security-model.md
Extend the security-review index with the new B5 syscall-boundary consolidated pass entry.
  • Add a 2026-05-29 row describing the B5 syscall boundary security review, verdict, and key findings
  • Link the new review document from the index table
docs/analysis/reviews/security-reviews/README.md
Add the standalone B5 syscall boundary security-review document capturing the eight-axis analysis and unsafe-audit cross-references.
  • Describe the scope, reviewer, and relationship to prior code review and ADRs for T-020/T-021 and PR B5 syscall boundary: error taxonomy (T-020) + EL0→EL1 SVC dispatch (T-021) #34
  • Provide detailed analysis along all eight security-review axes, including capability correctness, trust boundaries, memory safety, kernel-mode discipline, secrets/logging, dependencies, and threat-model impact
  • Record findings on UNSAFE-2026-0029 and UNSAFE-2026-0030, the copy-user disjointness invariant, and the reconciliation of security-model docs with ADR-0036, along with forward flags for B6 and Phase-E work
docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 099d65e5-b160-4694-8ea0-be043bfa1765

📥 Commits

Reviewing files that changed from the base of the PR and between f15ae9a and 6d142a2.

📒 Files selected for processing (2)
  • docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md
  • docs/roadmap/phases/phase-b.md
✅ Files skipped from review due to trivial changes (2)
  • docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md
  • docs/roadmap/phases/phase-b.md

📝 Walkthrough

Walkthrough

Adds a B5 syscall-boundary security review, B5 closure business and performance artifacts, security-model/IOMMU wording fixes, index/README updates, and marks B5 CLOSED while promoting B6.

Changes

B5 Syscall Boundary Security Review and Closure Artifacts

Layer / File(s) Summary
B5 Syscall Boundary Security Review Document
docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md
Standalone security review covering capability correctness (gating, non-forgeability, send semantics, IpcError granularity), trust boundaries (typed register decoding, pointer validation), memory safety (frame layout checks, copy-user disjointness correction), kernel-mode discipline (panic-free dispatcher), QEMU smoke evidence, secrets/logging redaction, dependencies (zero-extern), threat-model impact (Phase/E reconciliation and B6 deferred gates). Concludes with an Approve verdict and forward-flagged checklist.
Security model clarification & security reviews index
docs/architecture/security-model.md, docs/analysis/reviews/security-reviews/README.md
Clarifies that v1 QEMU virt CI does not gate on IOMMU (IOMMU gating is for IOMMU-equipped targets) and updates the open-question wording; registers the B5 syscall-boundary security review in the security reviews index.
Performance baseline and performance review
docs/analysis/reports/perf-baseline-2026-05-29-B5-closure.md, docs/analysis/reviews/performance-optimization-reviews/2026-05-29-B5-closure.md, docs/analysis/reviews/performance-optimization-reviews/README.md
Adds boot-to-end perf baseline and B5 closure perf review: ELF section size deltas, host test-count changes, boot timing distributions, hotspot analysis (SVC smoke cost), regression checklist, same-host control, and forward-flagged B6 measurement items.
Business-retrospective and index update
docs/analysis/reviews/business-reviews/2026-05-29-B5-closure.md, docs/analysis/reviews/business-reviews/README.md
Adds B5 closure retrospective documenting task promotions (T-020/T-021), ADRs, unsafe audit entries, test counts, QEMU smoke traces, performance deltas, lessons learned, adjustments checklist, and Next pointer to B6; updates business reviews index.
Roadmap, Phase B, and miscellaneous docs
docs/roadmap/current.md, docs/roadmap/phases/phase-b.md, CLAUDE.md, README.md, docs/architecture/boot.md, docs/architecture/memory-management.md, docs/architecture/task-loader.md
Marks Milestone B5 as CLOSED, updates headline metrics and links (T-020/T-021 merged), shifts active milestone to B6, updates ADR ledger and B6 prerequisites, and tweaks related documentation wording for consistency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • HodeTech/Tyrne#13: Related prior edit to IOMMU/SMMU/open-question wording in the security model.

Poem

🐰 I hopped through docs and closure trails,
Read SVC notes and copy-user scales,
Caps redacted, verdict signed and proved,
B5 is closed, B6 now smooths the groove,
A rabbit's nod for careful moves.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: formal closure of Milestone B5 through a documentation trilogy (security, performance, business reviews). It is concise, specific, and directly matches the changeset content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sec-review-b5-syscall-boundary

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md" line_range="90" />
<code_context>
+- **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
</code_context>
<issue_to_address>
**issue (typo):** ADR reference label and linked filename appear inconsistent (0033 vs 0027).

The link text says ADR-0033 but the path points to `0027-kernel-virtual-memory-layout.md`. Please confirm which ADR is intended and update either the label or the target so they refer to the same ADR.

```suggestion
- **Phase-deferred placeholders unchanged.** [ADR-0027](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docs/analysis/reviews/security-reviews/2026-05-29-B5-syscall-boundary.md Outdated
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds the security review documentation for the B5 syscall boundary (T-020 and T-021) and updates the security model documentation to align with the GICv2/no-IOMMU configuration of the QEMU virt target. Feedback on the new security review document highlights a mismatch in a quoted assertion regarding NULL_CAP_HANDLE compared to the actual implementation in abi.rs, as well as an incorrect link for ADR-0033.

- `task_yield` (3) / `task_exit` (4) take **no object-capability argument** — they act only on the caller's own task via the trusted current-task identity, which is the caller's inherent authority over its own execution thread (ADR-0031's "trust-boundary check is *is there a valid current task?*, plus the kernel never letting the caller name a *different* task"). No ambient authority over another object.
- **Adversarial probe — was `console_write` ever ambient authority?** It was, in the *first* ADR-0030/0031 draft (a P1/P4 violation), and was caught by the same-day maintainer review and folded into the ADR bodies **before Accept** (recorded in the 2026-05-29 `current.md` banner). The shipped code gates it on the debug-console cap. Verified by `dispatch::tests::console_write_with_no_cap_returns_cap_invalid_handle_no_output` (+ `…_wrong_kind…`, `…_without_write_right…`), each asserting the console captured **zero** bytes on a failed check.
- **The new capability surface is the narrowest possible addition, with no widening.** OK — `console_write` introduces exactly one new `CapObject::DebugConsole` (a **unit** variant — the debug console is a singleton with no per-instance kernel-object storage, so it carries no handle, the smallest object addition ADR-0031 names) + one new right `CapRights::CONSOLE_WRITE` (`1 << 7`, added to `KNOWN_BITS` so `from_raw` masks it correctly). The check requires *both* (right kind **and** the `CONSOLE_WRITE` right) — the narrowest sufficient authority; a debug-console cap minted with `CapRights::empty()` is correctly rejected (`…_without_write_right…` test). No existing check was widened.
- **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The quoted assertion assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX)) does not match the actual implementation in abi.rs, which uses as u64 casts: assert!(NULL_CAP_HANDLE > (((u32::MAX as u64) << 16) | (u16::MAX as u64))). Without these casts, u32::MAX << 16 would truncate/overflow in 32-bit arithmetic and fail to correctly represent the 48-bit maximum packed handle. The documentation should be updated to match the actual code.

Suggested change
- **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build.
- **`CapHandle::from_raw` (the new ABI-decode constructor) cannot forge authority.** OK — the syscall ABI decodes a userspace-supplied register word into a `CapHandle` via `CapHandle::from_raw(index, generation)` ([`cap/table.rs`](../../../../kernel/src/cap/table.rs)). The reconstructed handle is **not trusted**: every `CapHandle` is validated against the live slot's generation by `CapabilityTable::lookup` before use, so a forged / stale / out-of-range `(index, generation)` simply fails lookup with `CapError::InvalidHandle` → `SyscallError::Cap(InvalidHandle)`; it can never alias a live capability. The capability table remains per-subject and unforgeable ([ADR-0014](../../../decisions/0014-capability-representation.md)); `from_raw` only re-materialises a handle *into the caller's own table*. **Adversarial probe — can the null-handle sentinel collide with a live handle?** No — `encode_cap_handle` packs `(generation: u32) << 16 | (index: u16)` (bits 0..48); the sentinel `NULL_CAP_HANDLE = u64::MAX` sets bits 48..64. A `const _: () = assert!(NULL_CAP_HANDLE > (((u32::MAX as u64) << 16) | (u16::MAX as u64)))` in [`abi.rs`](../../../../kernel/src/syscall/abi.rs) locks this at build time (added in the review-round), so a future `CapHandle` widening that could collide fails the build.

- "`unsafe` is audited" — OK (§3: UNSAFE-2026-0029/0030 land under the Operation/Invariants/Rejected-alternatives shape; 0029 second-reviewer-signed).
- "Bounded kernel state / no unbounded allocation / panic-free on untrusted input" — OK (§4: typed `SyscallError` on every path; bounded chunk loop; no heap).
- "Fault containment does not leak authority" — **partially exercised; the dispatcher is panic-free, but full fault containment is Phase E.** A *dispatcher* failure returns a typed error (done). But a crashing EL0 task's fault (illegal instruction, unmapped deref) still routes to `panic_entry` → halt — the supervisor-endpoint `TaskFault` delivery is Phase E / flag K3-4 (recorded in [phase-b.md §B5 flags](../../../roadmap/phases/phase-b.md#flags-to-resolve-during-b5)). Non-blocking for B5 (no EL0 task to crash yet); confirmed-deferred per the B5 flag.
- **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The link for ADR-0033 incorrectly points to 0027-kernel-virtual-memory-layout.md (which is the file for ADR-0027). Since ADR-0033 is described as slot-reserved (similar to ADR-0034), the link should be removed or updated to point to the correct 0033-high-half-migration.md placeholder file if it exists.

Suggested change
- **Phase-deferred placeholders unchanged.** [ADR-0033](../../../decisions/0027-kernel-virtual-memory-layout.md) (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.
- **Phase-deferred placeholders unchanged.** ADR-0033 (high-half migration — gates the per-task `TTBR0_EL1` swap + kernel mappings in the userspace AS, the prerequisite for ever running a real EL0 task) and ADR-0034 (kernel-image / per-section permissions — gates the first attacker-observable EL0 execution) remain slot-reserved.

cemililik and others added 2 commits May 29, 2026 17:18
B5 closure performance baseline — the performance leg of the B5 syscall-boundary
closure trio. Re-baseline of kernel footprint + boot-to-end timing after T-020 +
T-021 (PR #34, f98e1af) versus the 2026-05-28 B4 closure baseline.

Footprint (release): .text 34,648 (+1,524) / .rodata 4,856 (+296) / .bss 50,592
(+2,272) = ~88.0 KiB (+4.76 %) — the smallest non-refactor .text growth in Phase
B (the syscall boundary is a thin validator/dispatch layer). Tests 339 (43 hal +
240 kernel + 53 test-hal + 3 doc; +53 kernel), miri clean (0 UB, run locally).
Release harness band p10/p50/p90 = 17.645 / 20.300 / 24.706 ms.

Verdict: baseline, no proposal. The cycle's decisive measurement was a same-host
back-to-back control (the B4 binary 3ab029f rebuilt + re-measured this session):
it proves the ~+2.9 ms p10/p50 delta vs B4 is REAL B5 code (the boot SVC-smoke —
2 exception round-trips + cold TCG translation), not host jitter, correcting an
initial mis-read of the noisier raw band. One-time-at-boot, ~us on real hardware.
The control also shows the QEMU-TCG harness is nearing its resolving floor for
small milestones (per-milestone signal ~ session jitter). Adds the harness report
docs/analysis/reports/perf-baseline-2026-05-29-B5-closure.md and the README index
row.

Refs: ADR-0013, ADR-0030, ADR-0031
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
B5 closure retrospective — the business leg of the B5 syscall-boundary closure
trio — plus the roadmap forward motion it drives. Formally closes Milestone B5
(Syscall boundary): T-020 (IpcError taxonomy split + Capability/CapObject Debug
redaction) + T-021 (EL0 to EL1 SVC dispatch) merged via PR #34 (f98e1af);
ADR-0030 + ADR-0031 Accepted.

What landed (canonical metrics, reproduced live at afeed10): 339 host tests
(+53 kernel) incl. local miri 0 UB; release ELF ~88.0 KiB (+4.76 % vs B4);
release smoke clean to "all tasks complete" (the release trace itself proves the
console_write debug-gate — status=0x1 in release); the debug smoke shows the full
console_write SVC round-trip (status=0x0, bytes=63); -d = 712/776 PL011 + 2
expected SVC exceptions (EL1 to EL1, ESR 0x15, clean ERET), zero new fault class;
audit log 30 entries (29 Active) — UNSAFE-2026-0029/0030.

What we learned: the pure-Rust (T-020) / hardware-boundary (T-021) split per
CLAUDE.md section 6 let the most security-sensitive milestone land safely in one
calendar day without skipping rigor; an adversarial pass + Miri corrected a real
copy-user soundness over-claim (disjointness, not the copy primitive, is the
basis); a same-host perf control corrected a host-jitter mis-attribution; ABI
front-loading kept the syscall numbers a decision, not an accident.

Side-effects: current.md banner + Pathfinder flipped to B5-closed / B6-next;
phase-b.md section B5 status -> Closed; test-count drift (236/240 mid-arc -> live
339) reconciled; business-reviews README index row added. Next: B6 (first
userspace "hello") — the deferred task_create_from_image bridge + the 3 T-021
carry-forward gates + the ADR-0033 high-half opening; B6's review is the Phase B
retrospective.

Refs: ADR-0013, ADR-0030, ADR-0031, ADR-0017, ADR-0033
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cemililik cemililik changed the title docs: B5 syscall-boundary security review (Approve) + ADR-0036 doc reconciliation docs(B5): closure trio — security + performance + business (close Milestone B5) May 29, 2026
…quence

Pre-B6 documentation preparation on the B5-closure branch (rides in PR #35),
done before B6 development starts on its own branch off main. Docs-only.

(1) B5-done status reconcile (drift sweep). With B5 closed, several live docs
still treated the syscall boundary as future/next:
- CLAUDE.md: "the syscall ABI and first userspace task are next" -> the syscall
  boundary is done; the first EL0 task is next.
- README.md status table: "Syscall ABI + EL0 entry | Next - Phase B5" -> split
  into "Syscall ABI + dispatcher = Done (B5)" + "First userspace hello (EL0) =
  Next (B6)".
- phase-b ADR ledger: ADR-0030 / ADR-0031 marked Accepted 2026-05-29; ADR-0033 /
  ADR-0034 triggers corrected from B5/B5+ to B6 (B5 closed via the SVC proxy
  without surfacing the per-task TTBR0 swap, so the trigger is now B6).
- architecture docs (task-loader / memory-management / boot): "ADR-0033 gated on
  B5 surfacing per-task TTBR0 swap" -> B6, and "until B5 adds a per-task context
  surface" -> B6 — these would have misled a B6 dev about which milestone owns
  the EL0 context + high-half work.

(2) B6 opening sequence & prerequisites — the careful B6 plan, made durable in
phase-b.md section B6. States the gating prerequisite (the kernel must stay
reachable from every task's active translation, else an EL0 SVC vector fetch
translation-faults), the ADRs that open B6 (ADR-0033 kernel-in-every-AS + the
EL0-task-context decision + optional ADR-0034), and the dependency-ordered task
sequence: ADR-0033 impl -> EL0 context -> task_create_from_image -> the 3 T-021
carry-forward gates -> tyrne-user + userland/hello -> wire-up + EL0 round-trip
smoke -> Phase B retrospective. Decisions remain open for their ADRs; this fixes
only the order + rationale.

All links resolve; docs-only, no kernel changes.

Refs: ADR-0013, ADR-0027, ADR-0030, ADR-0031, ADR-0033
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@docs/roadmap/phases/phase-b.md`:
- Around line 315-316: The table row for ADR-0034 contains an unescaped pipe
inside inline code (`USER|EXECUTE`) which makes the Markdown parser treat the
row as five columns; update the ADR-0034 row in phase-b.md to escape the pipe
inside the inline code (e.g., change `USER|EXECUTE` to `USER\|EXECUTE`) so the
table remains four columns like ADR-0033, ensuring the rest of the row text and
links (ADR-0034, ADR-0033, references to ADR-0027 and memory-management.md) are
unchanged.
🪄 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: 72daf8c4-4651-46fa-acea-c0d2f178f223

📥 Commits

Reviewing files that changed from the base of the PR and between 0b665db and f15ae9a.

📒 Files selected for processing (6)
  • CLAUDE.md
  • README.md
  • docs/architecture/boot.md
  • docs/architecture/memory-management.md
  • docs/architecture/task-loader.md
  • docs/roadmap/phases/phase-b.md
✅ Files skipped from review due to trivial changes (5)
  • docs/architecture/boot.md
  • CLAUDE.md
  • docs/architecture/memory-management.md
  • docs/architecture/task-loader.md
  • README.md

Comment thread docs/roadmap/phases/phase-b.md Outdated
… table pipe

Three review findings on the B5 closure docs, each verified against the source:

- abi.rs assert quote (security review section 1): the doc quoted
  assert!(NULL_CAP_HANDLE > ((u32::MAX << 16) | u16::MAX)) but the actual
  abi.rs:42 uses `as u64` casts — (((u32::MAX as u64) << 16) | (u16::MAX as u64))
  (without them the shift overflows in u32 arithmetic). Quote corrected to match.

- ADR-0033 link (security review section 8): the label said "ADR-0033" but the
  link targeted 0027-kernel-virtual-memory-layout.md (a mismatch). ADR-0033
  (high-half migration) is genuinely the right concept — 0027 only reserves the
  slot — so rather than relabel to ADR-0027 (which would misattribute high-half
  to 0027), ADR-0033 is now plain text (matching the unlinked ADR-0034 in the
  same sentence) with a correctly-labeled "reserved in ADR-0027" cross-reference.

- ADR-0034 ledger row (phase-b.md): the inline code USER|EXECUTE (introduced in
  the pre-B6 prep commit) had an unescaped pipe, splitting the table row into
  five columns; escaped to USER\|EXECUTE. All 14 ledger rows now have 4 columns.

Validated: assert quote matches abi.rs:42 verbatim; all links resolve; every
ADR-ledger row is well-formed (5 delimiters = 4 columns). Docs-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cemililik cemililik merged commit bd39679 into main May 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant