Skip to content

B6: T-024 — task_create_from_image (LoadedImage → runnable Task capability)#38

Merged
cemililik merged 3 commits into
mainfrom
t-024-task-create-from-image
May 31, 2026
Merged

B6: T-024 — task_create_from_image (LoadedImage → runnable Task capability)#38
cemililik merged 3 commits into
mainfrom
t-024-task-create-from-image

Conversation

@cemililik
Copy link
Copy Markdown
Collaborator

@cemililik cemililik commented May 31, 2026

B6 step 3 (the deferred B4 §3 bridge): task_create_from_image turns a LoadedImage into a runnable CapHandle{CapObject::Task(...)}. It mints, does not schedule — running the task is the later B6 wire-up.

What lands

  • task_create_from_image(loaded, table, task_arena, id, task_rights) -> Result<CapHandle, TaskCreateError> (kernel/src/obj/task_loader.rs): (1) resolve loaded.as_capAddressSpaceHandle (lookup + CapKind::AddressSpace kind-check); (2) create_task(Task::new(id, ash)); (3) Capability::new(task_rights, CapObject::Task(handle))insert_root. Rollback on a full cap-table (destroy_task → no orphaned arena slot).
  • TaskCreateError (InvalidAddressSpaceCap / TaskArenaFull / CapTableExhausted), re-exported from crate::obj.
  • Kind-only Task cap (v1): mirrors the CapKind::AddressSpace model — no Task-operation right; task_rights govern only cap management. No new ADR (composes ADR-0029/0028/0016/0037). No new unsafe.
  • 4 host tests: mint + AS-binding + id; wrong-kind as_cap; stale as_cap; rollback-on-cap-table-exhausted (slot-0 reuse proves no leak).

Dormant

No BSP caller yet — the QEMU trace is byte-stable. Running a real EL0 task (via add_user_task with the image's entry/stack) is the wire-up, gated behind the T-021 carry-forward gates (gate #1 per-task user-VA translation; gate #3 current-task cap table).

Review

An adversarial multi-agent review (4 lenses × per-finding verification) found 6 findings, all Low/Nit, no code/security/correctness defect (borrow scoping, rollback, error mapping, kind-only model, and the tests verified correct). 4 fixed in ad13d12 (module-doc surface, a stale current.md line, a redundant rustdoc link target, an ObjError-map clarifying comment); 2 deferred-with-tracking (the AS-handle/Task lifecycle coupling — a carry-forward precondition for the wire-up / a successor lifecycle ADR; and a future generic lookup_kind cap helper). Security-relevant (cap minting); T-024's formal code security review remains a DoD item before the wire-up runs a real EL0 task.

Gates

cargo fmt · host + kernel clippy -D warnings · 347 host tests (+4) · kernel build · QEMU smoke byte-stable + fault-clean (dormant) · cargo +nightly miri test --workspace --exclude tyrne-bsp-qemu-virt 0 UB.

🤖 Generated with Claude Code

Summary by Sourcery

Introduce a kernel helper that mints a runnable Task capability from a loaded userspace image, along with documentation and roadmap updates describing this new bridge in the Phase B plan.

New Features:

  • Add task_create_from_image to convert a LoadedImage into a Task kernel object and root Task capability without scheduling it.
  • Define a TaskCreateError error taxonomy for failures when creating tasks from images and re-export it from the object module.

Enhancements:

  • Extend object module documentation to cover the new task_create_from_image bridge and update status to include T-024.
  • Refine roadmap and task analysis documents to describe T-024’s role in the B6 milestone and record its implementation status and review history.

Tests:

  • Add host tests covering successful task creation and binding, wrong-kind and stale address-space capabilities, and rollback behavior when the capability table is exhausted.

Summary by CodeRabbit

  • New Features
    • Added ability to mint runnable task objects from loaded images (created but not scheduled).
  • Documentation
    • Comprehensive docs for the task-creation bridge, expected behavior, error/rollback taxonomy, acceptance criteria, and explicit out-of-scope items.
    • Updated roadmap to mark the new task workstream status and milestones.
  • Tests
    • New unit tests covering success, wrong-kind/stale address-space cases, resource-exhaustion rollback, and arena-full failure.

cemililik and others added 2 commits May 31, 2026 13:59
…sk capability)

The deferred B4 §3 / B6-step-3 bridge: turns a LoadedImage into a runnable
CapHandle{CapObject::Task(...)}. It resolves the loaded address space from
loaded.as_cap (lookup + CapKind::AddressSpace kind-check), mints a Task kernel
object bound to it (create_task), and installs a root CapKind::Task capability
naming it (insert_root), returning the CapHandle.

- Mints, does not schedule. Running the task is the B6 wire-up's job (it calls
  Scheduler::add_user_task with the image's entry_va/stack_top_va — the EL0
  entry context lives in the cooperative context per ADR-0037, not on the Task
  object, so task_create_from_image reads only loaded.as_cap), and not before
  the T-021 carry-forward gates (gate #1 per-task user-VA translation, gate #3
  current-task cap table) close. Dormant in v1: no BSP caller, so the QEMU
  trace is byte-stable.
- Rollback: if insert_root hits a full cap-table (CapsExhausted), the just-
  created task object is destroyed (arena slot freed) so no orphaned task
  leaks. Pinned by a host test (slot 0 reused after the failed create).
- TaskCreateError: InvalidAddressSpaceCap(CapError) (stale / wrong-kind
  as_cap), TaskArenaFull, CapTableExhausted(CapError). Re-exported from
  crate::obj.
- v1 cap-rights model: the Task cap is kind-only (CapKind::Task names/authorizes
  the task object), mirroring the CapKind::AddressSpace model; task_rights
  govern only cap management. No Task-operation right; no new ADR. No new unsafe.

Composes ADR-0029 (loader) + ADR-0028 (AS cap) + ADR-0016 (kernel object) +
ADR-0037 (EL0 context). New host tests: mint + AS-binding + id; wrong-kind
as_cap; stale as_cap; rollback-on-cap-table-exhausted.

Gates: cargo fmt; host + kernel clippy -D warnings; 347 host tests (+4);
kernel build; QEMU smoke byte-stable + fault-clean (dormant); cargo +nightly
miri test --workspace --exclude tyrne-bsp-qemu-virt clean (0 UB).

Security-relevant (cap minting + AS-cap resolution + rollback); flagged for
explicit security review per the task's Definition of done.

Refs: T-024, ADR-0029, ADR-0028, ADR-0037
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oc drift, ObjError-map comment

Folds in an adversarial multi-agent review of T-024 (4 lenses × per-finding
verification): 6 findings, all confirmed Low/Nit, no code/security/correctness
defect (the borrow scoping, rollback, error mapping, kind-only model, and the
4 host tests were verified correct). Fixed:

- CC-001 (Low) — obj/mod.rs module-doc was stale: it omitted the new
  task_create_from_image / TaskCreateError surface and still asserted the
  loader does NOT mint a runnable CapHandle{CapObject::Task(...)} (now false).
  Updated the surface list + the load_image/task_create_from_image split note
  + the Status heading.
- DOC-1 (Low) — current.md retained a "Next to open: task_create_from_image"
  sentence (historical T-022 prose) that contradicted the same bullet's T-024
  lead; removed (the T-024 lead's own "Next:" supersedes it).
- DOC-2 (Nit) — dropped the redundant explicit `[crate::mm::cap_map]` target
  on the fn doc's `[cap_map]` link (rustdoc redundant-target warning).
- T024-C-N1 (Nit) — added a comment pinning that create_task only returns
  ObjError::ArenaFull, so the map_err(|_| TaskArenaFull) is exhaustive by
  contract (not a lossy catch-all).

Deferred (tracked in the T-024 task doc, no code change):
- SEC-T024-01 (Nit) — the minted Task cap stores an AddressSpaceHandle whose
  liveness is not coupled to the AS cap; dormant + out of scope (mints, does
  not schedule) + a pre-existing v1 object-lifecycle gap (ADR-0016). Recorded
  as a carry-forward precondition for the B6 wire-up / the successor lifecycle
  ADR (a Task must not outlive / alias a reused slot of its bound AS).
- CC-002 (Nit) — the inline AS-cap resolve duplicates the module-private
  resolve_address_space_cap; reuse is not cleanly available (error-taxonomy
  coupling). Tracked as a future generic CapabilityTable::lookup_kind helper.

Gates: cargo fmt; host + kernel clippy -D warnings; 347 host tests; the
DOC-2 rustdoc warning is gone (kernel binary unchanged → prior byte-stable
QEMU smoke + Miri 0 UB hold).

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

sourcery-ai Bot commented May 31, 2026

Reviewer's Guide

Implements task_create_from_image as the bridge from a LoadedImage to a runnable Task capability, adds an error taxonomy and tests around it, and updates documentation/roadmap to reflect the new T-024 task and API surface.

Sequence diagram for task_create_from_image minting a Task capability

sequenceDiagram
    participant Caller
    participant CapabilityTable
    participant TaskArena
    participant TaskLoader

    Caller->>TaskLoader: task_create_from_image(loaded, table, task_arena, id, task_rights)

    rect rgb(230,230,230)
        Note over TaskLoader,CapabilityTable: Step 1 — resolve loaded.as_cap to AddressSpaceHandle
        TaskLoader->>CapabilityTable: lookup(loaded.as_cap)
        alt [CapError::InvalidHandle or CapError::WrongKind]
            CapabilityTable-->>TaskLoader: Err(CapError)
            TaskLoader-->>Caller: Err(TaskCreateError::InvalidAddressSpaceCap)
        else [CapObject::AddressSpace(handle)]
            CapabilityTable-->>TaskLoader: Ok(Capability)
            TaskLoader->>TaskLoader: extract AddressSpaceHandle
        end
    end

    rect rgb(230,230,230)
        Note over TaskLoader,TaskArena: Step 2 — mint Task object in arena
        TaskLoader->>TaskArena: create_task(task_arena, Task::new(id, as_handle))
        alt [arena full]
            TaskArena-->>TaskLoader: Err(ObjError::ArenaFull)
            TaskLoader-->>Caller: Err(TaskCreateError::TaskArenaFull)
        else [task created]
            TaskArena-->>TaskLoader: Ok(task_handle)
        end
    end

    rect rgb(230,230,230)
        Note over TaskLoader,CapabilityTable: Step 3 — install root Task capability
        TaskLoader->>CapabilityTable: insert_root(Capability::new(task_rights, CapObject::Task(task_handle)))
        alt [success]
            CapabilityTable-->>TaskLoader: Ok(task_cap: CapHandle)
            TaskLoader-->>Caller: Ok(task_cap)
        else [CapError::CapsExhausted]
            CapabilityTable-->>TaskLoader: Err(CapError::CapsExhausted)
            TaskLoader->>TaskArena: destroy_task(task_arena, task_handle)
            TaskArena-->>TaskLoader: Ok(())
            TaskLoader-->>Caller: Err(TaskCreateError::CapTableExhausted)
        end
    end
Loading

File-Level Changes

Change Details Files
Introduce task_create_from_image API to mint a Task object and root Task capability from a LoadedImage, with rollback on cap-table exhaustion and a dedicated TaskCreateError taxonomy.
  • Define non_exhaustive TaskCreateError enum with InvalidAddressSpaceCap, TaskArenaFull, and CapTableExhausted variants mapping from CapError/arena conditions.
  • Implement task_create_from_image that resolves loaded.as_cap to an AddressSpaceHandle with kind-checking, creates a Task in the TaskArena, and inserts a root CapKind::Task capability into the CapabilityTable.
  • Ensure rollback by destroying the newly-created Task when capability table insertion fails due to CapsExhausted, preventing orphaned arena slots.
kernel/src/obj/task_loader.rs
Add focused tests around task_create_from_image behavior and LoadedImage usage, validating success path, error paths, and rollback semantics.
  • Introduce helper to construct LoadedImage instances with arbitrary as_cap while other fields are opaque for this function.
  • Add tests for successful minting binding to the correct address space and id, wrong-kind as_cap rejection, stale as_cap rejection, and rollback when the capability table is exhausted.
  • Use TaskArena and CapabilityTable fixtures to assert arena slot reuse after rollback, proving no leaks.
kernel/src/obj/task_loader.rs
Update object module exports and documentation plus roadmap/analysis docs to describe T-024 and the new task_create_from_image bridge.
  • Document task_create_from_image and TaskCreateError in obj/mod.rs module docs, clarifying that it mints a runnable Task capability but does not schedule.
  • Re-export TaskCreateError from crate::obj to make the error type available to callers.
  • Update docs/roadmap/current.md to mark T-024 as the active task, describe its implementation status, and adjust the working-branch narrative.
  • Add a new analysis doc for T-024 detailing context, acceptance criteria, approach, and review history for task_create_from_image.
kernel/src/obj/mod.rs
docs/roadmap/current.md
docs/analysis/tasks/phase-b/T-024-task-create-from-image.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 31, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b868ed5c-8e71-459d-8758-ad14d47647ca

📥 Commits

Reviewing files that changed from the base of the PR and between ad13d12 and ba81159.

📒 Files selected for processing (1)
  • kernel/src/obj/task_loader.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • kernel/src/obj/task_loader.rs

📝 Walkthrough

Walkthrough

This PR implements the task_create_from_image bridge that converts a successfully loaded address space (LoadedImage) into a minted CapObject::Task capability; it updates docs/roadmap/module re-exports, adds TaskCreateError and the public API, implements minting/insert/rollback logic, and adds unit tests.

Changes

Task creation feature

Layer / File(s) Summary
Feature specification and public API contract
docs/analysis/tasks/phase-b/T-024-task-create-from-image.md, docs/roadmap/current.md, kernel/src/obj/mod.rs
T-024 docs and roadmap define the bridge signature, stepwise flow (AS-cap resolution + kind check, task arena object creation, root cap insertion), rollback semantics, TaskCreateError taxonomy, and out-of-scope items. Module docs clarify phase separation and re-export TaskCreateError.
Task creation implementation and tests
kernel/src/obj/task_loader.rs
Imports task-minting/teardown and arena types. Adds TaskCreateError and task_create_from_image that resolves the address-space capability, verifies kind/liveness, mints a Task in TaskArena, inserts a root task capability into the CapabilityTable, and destroys the minted task if table insertion fails. Adds unit tests covering success, wrong-kind/stale AS caps, rollback on cap-table exhaustion, and arena-full rejection.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant CapabilityTable
  participant TaskArena
  Caller->>CapabilityTable: resolve loaded.as_cap
  CapabilityTable-->>Caller: CapHandle / error
  Caller->>Caller: verify CapKind == AddressSpace
  Caller->>TaskArena: create_task(bound to AS)
  TaskArena-->>Caller: TaskId / TaskArenaFull
  Caller->>CapabilityTable: insert CapKind::Task root cap
  CapabilityTable-->>Caller: success / CapTableExhausted
  alt CapTableExhausted
    Caller->>TaskArena: destroy_task(TaskId)
    TaskArena-->>Caller: destroyed
  end
  Caller-->>Caller: return Result<CapHandle, TaskCreateError>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • HodeTech/Tyrne#31: Implements load_image that produces the LoadedImage consumed by this PR's task_create_from_image.
  • HodeTech/Tyrne#2: Adds core CapObject/task-arena primitives used by the new task creation and tests.

Poem

🐰 I held the bytes and gave them legs,
Minted a task with careful pegs.
If slots ran dry or tables choke,
I tidy up — no orphaned folk.
Hop, test, and shine — the bridge is made.

🚥 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 clearly and specifically summarizes the main change: implementing task_create_from_image to convert a LoadedImage into a runnable Task capability.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t-024-task-create-from-image

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

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 implements the task_create_from_image bridge (T-024), which transitions a LoadedImage into a runnable CapObject::Task capability. It resolves the loaded address space capability, mints a Task kernel object, and inserts a root CapKind::Task capability into the capability table, with a rollback mechanism to prevent orphaned task slots if the capability table is full. The reviewer suggested masking the task_rights to only allow capability management rights (DUPLICATE, DERIVE, REVOKE, TRANSFER) when minting the root Task capability to adhere to the principle of least privilege.

// 3 — install a root Task capability. On a full cap-table, roll the task
// object back so no orphaned arena slot leaks (the handle was just
// created, so `destroy_task` succeeds; the recovered `Task` is dropped).
let cap = Capability::new(task_rights, CapObject::Task(task_handle));
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

Since the Task capability in v1 is kind-only and does not carry any task-operation rights, any rights other than capability management rights (DUPLICATE, DERIVE, REVOKE, TRANSFER) are meaningless and could violate the principle of least privilege if granted. It is safer to mask task_rights to ensure only capability management rights are allowed when minting the root Task capability.

    let allowed_rights = task_rights & (CapRights::DUPLICATE | CapRights::DERIVE | CapRights::REVOKE | CapRights::TRANSFER);
    let cap = Capability::new(allowed_rights, CapObject::Task(task_handle));

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, and left some high level feedback:

  • In task_create_from_image, TaskCreateError::CapTableExhausted currently assumes insert_root only returns CapsExhausted; if that contract ever widens, this mapping becomes misleading, so consider either matching explicitly on CapError::CapsExhausted (and handling others separately) or adding a defensive assertion to keep the assumption checked.
  • When rolling back after a failed insert_root, the destroy_task result is discarded; given the comment that it "succeeds", it would be safer to debug_assert!(destroy_task(..).is_ok()) (or at least log failures) to catch violations of that assumption early.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `task_create_from_image`, `TaskCreateError::CapTableExhausted` currently assumes `insert_root` only returns `CapsExhausted`; if that contract ever widens, this mapping becomes misleading, so consider either matching explicitly on `CapError::CapsExhausted` (and handling others separately) or adding a defensive assertion to keep the assumption checked.
- When rolling back after a failed `insert_root`, the `destroy_task` result is discarded; given the comment that it "succeeds", it would be safer to `debug_assert!(destroy_task(..).is_ok())` (or at least log failures) to catch violations of that assumption early.

## Individual Comments

### Comment 1
<location path="kernel/src/obj/task_loader.rs" line_range="944-948" />
<code_context>
+    //     object back so no orphaned arena slot leaks (the handle was just
+    //     created, so `destroy_task` succeeds; the recovered `Task` is dropped).
+    let cap = Capability::new(task_rights, CapObject::Task(task_handle));
+    match table.insert_root(cap) {
+        Ok(task_cap) => Ok(task_cap),
+        Err(e) => {
+            let _ = destroy_task(task_arena, task_handle);
+            Err(TaskCreateError::CapTableExhausted(e))
+        }
+    }
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Align `CapTableExhausted` semantics with the documented `CapsExhausted`-only expectation.

This branch currently wraps any `CapError` from `insert_root` in `CapTableExhausted`, which contradicts the documented “wraps `CapError::CapsExhausted`” contract and could mislead callers if other variants are ever returned. Either enforce the contract with `debug_assert!(matches!(e, CapError::CapsExhausted))`, or match on `CapError` explicitly and route non-`CapsExhausted` variants to a different `TaskCreateError` (or mark them unreachable) to keep the error taxonomy accurate.

Suggested implementation:

```rust
    let cap = Capability::new(task_rights, CapObject::Task(task_handle));
    match table.insert_root(cap) {
        Ok(task_cap) => Ok(task_cap),
        Err(e) => {
            let _ = destroy_task(task_arena, task_handle);
            Err(TaskCreateError::CapTableExhausted(e))
        }
    }

```

```rust
    let cap = Capability::new(task_rights, CapObject::Task(task_handle));
    match table.insert_root(cap) {
        Ok(task_cap) => Ok(task_cap),
        Err(e) => {
            debug_assert!(matches!(e, CapError::CapsExhausted));
            let _ = destroy_task(task_arena, task_handle);
            Err(TaskCreateError::CapTableExhausted(e))
        }
    }

```
</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 kernel/src/obj/task_loader.rs
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.

🧹 Nitpick comments (1)
kernel/src/obj/task_loader.rs (1)

1088-1212: ⚡ Quick win

Add a dedicated TaskArenaFull test case.

TaskCreateError::TaskArenaFull is part of the public taxonomy but currently unpinned by tests. Adding one focused test will lock this branch against regressions.

Proposed test addition
@@
     #[test]
     fn task_create_from_image_rolls_back_task_on_cap_table_exhausted() {
@@
     }
+
+    #[test]
+    fn task_create_from_image_returns_task_arena_full() {
+        let (mut table, as_cap, _mmu, _arena, _pmm, _b) = fixture(16);
+        let expected_ash = match table.lookup(as_cap).unwrap().object() {
+            CapObject::AddressSpace(h) => h,
+            other => panic!("not an AS cap: {other:?}"),
+        };
+        let loaded = loaded_image_with(as_cap);
+        let mut task_arena = TaskArena::default();
+
+        // Fill task arena completely.
+        while create_task(&mut task_arena, Task::new(0, expected_ash)).is_ok() {}
+
+        assert_eq!(
+            task_create_from_image(&loaded, &mut table, &mut task_arena, 1, CapRights::empty()),
+            Err(TaskCreateError::TaskArenaFull),
+        );
+    }
🤖 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/obj/task_loader.rs` around lines 1088 - 1212, Add a new unit test
that asserts task_create_from_image returns TaskCreateError::TaskArenaFull when
the TaskArena is exhausted: use fixture(...) to obtain a valid as_cap, create a
TaskArena via TaskArena::default(), pre-fill the arena until it reports full
(e.g. by repeatedly calling create_task(Task::new(...)) or otherwise allocating
until allocation fails), then call task_create_from_image(&loaded, &mut table,
&mut task_arena, id, CapRights::empty()) and assert it returns
Err(TaskCreateError::TaskArenaFull(...)); reference task_create_from_image,
TaskArena, TaskArena::default, create_task, Task::new and
TaskCreateError::TaskArenaFull to locate where to add this test alongside the
existing task_create_from_image_* tests.
🤖 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.

Nitpick comments:
In `@kernel/src/obj/task_loader.rs`:
- Around line 1088-1212: Add a new unit test that asserts task_create_from_image
returns TaskCreateError::TaskArenaFull when the TaskArena is exhausted: use
fixture(...) to obtain a valid as_cap, create a TaskArena via
TaskArena::default(), pre-fill the arena until it reports full (e.g. by
repeatedly calling create_task(Task::new(...)) or otherwise allocating until
allocation fails), then call task_create_from_image(&loaded, &mut table, &mut
task_arena, id, CapRights::empty()) and assert it returns
Err(TaskCreateError::TaskArenaFull(...)); reference task_create_from_image,
TaskArena, TaskArena::default, create_task, Task::new and
TaskCreateError::TaskArenaFull to locate where to add this test alongside the
existing task_create_from_image_* tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d44d68f-6f18-4f6f-9b8d-801bfab9e444

📥 Commits

Reviewing files that changed from the base of the PR and between eb3125f and ad13d12.

📒 Files selected for processing (4)
  • docs/analysis/tasks/phase-b/T-024-task-create-from-image.md
  • docs/roadmap/current.md
  • kernel/src/obj/mod.rs
  • kernel/src/obj/task_loader.rs

…ebug_assert, rollback/rights docs

Folds in a second T-024 review. Each finding verified against the code:

- Add the missing TaskArenaFull test (task_create_from_image_rejects_when_
  task_arena_full): fill the TaskArena via create_task until full, then
  task_create_from_image returns Err(TaskCreateError::TaskArenaFull). Closes
  the one untested error branch.
- CapTableExhausted assumed insert_root only returns CapsExhausted: that holds
  today (cap/table.rs), so a debug_assert!(matches!(e, CapsExhausted)) now pins
  the assumption — a future widening of insert_root's contract is caught in
  debug rather than silently mislabelled.
- Rollback assertion: the reviewer's literal `debug_assert!(destroy_task(..).
  is_ok())` would be a RELEASE BUG — debug_assert! strips its argument in
  release, so destroy_task would not be called and the task slot would leak.
  Kept the unconditional `let _ = destroy_task(..)` rollback and documented why
  it is deliberately NOT debug_assert-wrapped (and that destroy_task cannot
  fail for a just-created handle: it deallocates a live generation-matched slot
  with no reachability check).

Skipped (with reason): masking task_rights to cap-management bits. Not a
security fix — in the kind-only Task-cap model, object-operation rights
(SEND/RECV/NOTIFY/CONSOLE_WRITE) are INERT on a Task cap (no operation gates on
them; a Task cap fails the CapKind check on, e.g., console_write regardless of
CONSOLE_WRITE). Silent masking diverges from the cap model's convention
(callers choose rights at mint; operations gate on the relevant right; no other
mint masks), would surprise callers, and is future-fragile (it would silently
drop a future Task-operation right). A uniform Task-cap rights policy, if ever
wanted, is an ADR-level decision, not a per-site mask. Instead the fn doc now
guides callers to pass only cap-management rights.

Gates: cargo fmt; host + kernel clippy -D warnings; 348 host tests (+1);
QEMU smoke byte-stable + fault-clean (dormant); Miri 0 UB.

Refs: T-024
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cemililik cemililik merged commit 5f17a30 into main May 31, 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