Skip to content

lua: native modules come only from the READ-only libs grant - #27

Merged
SnowCheetos merged 3 commits into
alphafrom
ft/cool-bardeen-f86yix
Oct 16, 2026
Merged

SnowCheetos merged 3 commits into
alphafrom
ft/cool-bardeen-f86yix

Conversation

@SnowCheetos

@SnowCheetos SnowCheetos commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Pairs with MicroPerceptron/kore#1288 (https://github.com/MicroPerceptron/kore/pull/1288), which closes a provenance hole in native require: the Lua bridge searched the task's own writable tree before libs/ for native .so modules, and the store let any writer set the EXECUTABLE_IMAGE stamp that was the loader's only gate.

Upstream (kore) now:

  • takes an attesting subtype (EXECUTABLE_IMAGE, PACKAGE_MANIFEST, unknown) only through BIND_EXECUTABLE, at create and on every later byte change of the stamped object;
  • resolves native modules inside kore-late itself through the task's READ-only libs grant (entered as a grant, never a path walk; a writable libs edge is refused with LoadError::LibsWritable). Loader::load_native(fs, stem) no longer takes a search list.

This PR is the libkore half:

  • native/ re-exported from kore d929d9a with tools/sync-native.py (the snapshot was 750 commits behind kore main; both lockfiles follow — virtio-accel-* 0.3.10 → 0.4.1 comes from kore's owners).
  • crates/lua/src/bridge.rs: SOURCE_SEARCH (own tree, then libs) for .lua sources only; load_native(fs, stem); refusal text for LibsWritable.
  • crates/ffi: the resync brought kore's newer ProviderError::Retiring; KoreProviderError::Retiring = 16 is appended (additive, like Timeout = 15: existing discriminants and the completion record's layout are unchanged), mapped, and extern/c/include/kore.h regenerated with cbindgen 0.29.4.
  • docs/lua.md: the require rule as it now stands.

kore pins this head (995dedb) for kore-std, kore-wasi and kore-lua; the two land together.

Verification

  • libkore, on 995dedb: make fmt, check, test, owners, docs, bindings-check, cross, miri — all pass locally.
  • kore: make user-svc-verify PASS against ef7ad53 (it is what caught kore-lua as the loader's second consumer); 995dedb differs only in kore-ffi, which kore's graph does not build. Plus kore's gate list in kore#1288.
  • Advisories is red on alpha too (wasmtime 48.0.5, RUSTSEC-2026-0354…0363, published 2026-10-14) — not this PR's; see the comment below for the proposed bump.
  • Copilot's five native/ / adapter findings are answered on their threads: upstream kore issues #1289, #1290 (and existing #1210), and libkore wasi: a Ctrl-C Interrupt record on guest stdio is treated as a protocol error and closes all three streams #28.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BDbTpiJFNzUJDBdjhHtXDm

Pairs with MicroPerceptron/kore ft/cool-bardeen-f86yix (d929d9a): the
store now takes an attesting subtype (EXECUTABLE_IMAGE) only through
BIND_EXECUTABLE, at create and on every later byte change, and kore-late
resolves native modules itself through the task's READ-only `libs` grant
(never a path walk, never the task's own tree), refusing a `libs` edge
the task could write beneath (LoadError::LibsWritable).

`native/` is re-exported from that kore revision with
tools/sync-native.py (it was 750 commits behind kore main; both
lockfiles follow).  The bridge's `require` keeps its source search (own
tree, then libs) and drops the native one: `Loader::load_native(fs,
stem)`, plus the LibsWritable refusal text.  docs/lua.md states the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDbTpiJFNzUJDBdjhHtXDm
Copilot AI balanced review requested due to automatic review settings October 15, 2026 21:44

Copy link
Copy Markdown
Contributor Author

CI status on ef7ad53:

  • targets (x86_64/aarch64/riscv64gc) and miri — this PR's, fix coming. The native/ resync brought in kore's newer ProviderError::Retiring, and kore-ffi's provider_class (crates/ffi/src/session.rs) matches it exhaustively. kore's own build never compiles kore-ffi, which is why kore's user-svc-verify did not see it. The fix appends KoreProviderError::Retiring = 16, which is ABI-additive like TIMEOUT = 15: existing discriminants keep their values and the struct layout is unchanged. It also maps the variant and regenerates extern/c/include/kore.h with cbindgen 0.29.4. make check already passes locally; the rest of the gate list is running before the push.
  • Advisories — not this PR's; red on alpha too. cargo audit flags wasmtime 48.0.5 (RUSTSEC-2026-0354…0363, published 2026-10-14, fixed in >=48.0.6, <49). alpha's Cargo.lock already pins 48.0.5, and this PR does not change it. No open PR bumps it yet. Proposed separate fix: cargo update -p wasmtime --precise 48.0.6, which also moves the wasmtime-internal-* crates. Kore's user graph is unaffected, because it patches wasmtime to its own vendor/wasmtime.

Generated by Claude Code

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Queue recovery, DMA retirement guarantees, deferred cleanup, and WASI interrupt handling have unresolved correctness issues.

5 open findings
What changed in this PR

Restricts Lua native modules to the READ-only libs grant, alongside a broad refresh of libkore’s exported native dependencies.

Changes:

  • Separates Lua source searches from grant-only native loading.
  • Adds executable-stamp authority checks and documents module provenance.
  • Imports upstream storage, runtime, driver, and ABI updates.
File Description
native/​services/​extract/​fuzz/​Cargo.lock Adds runtime dependency.
native/​crates/​window/​src/​lib.rs Adds window lifecycle constants.
native/​crates/​window/​src/​client.rs Adds multi-plane wake support.
native/​crates/​rt/​src/​transport/​mod.rs Requires debuggable transport errors.
native/​crates/​rt/​src/​thread.rs Updates worker mesh sizing.
native/​crates/​rt/​src/​svc/​serve.rs Adds background progress and cleanup rechecks.
native/​crates/​rt/​src/​svc/​mod.rs Extends diagnostics and capture framing.
native/​crates/​rt/​src/​star.rs Updates worker kicks and mesh limits.
native/​crates/​rt/​src/​session/​tests.rs Tests sink mappings and guest cohorts.
native/​crates/​rt/​src/​session/​builder.rs Adds mapping and retirement operations.
native/​crates/​rt/​src/​service/​mod.rs Adds background polling hook.
native/​crates/​rt/​src/​process/​interrupt.rs Adds bounded interrupt policy.
native/​crates/​rt/​src/​pinned.rs Formats test assertion.
native/​crates/​rt/​src/​heap/​source.rs Formats heap implementation.
native/​crates/​rt/​src/​heap/​mod.rs Reorders exports.
native/​crates/​rt/​src/​entry.rs Adds stream-host attachment claim.
native/​crates/​rt/​src/​chan.rs Adds task delegation and notice rearming.
native/​crates/​rt/​src/​cap/​mod.rs Extends route inspection and DMA retirement.
native/​crates/​rt/​src/​barrier.rs Updates mesh documentation.
native/​crates/​rt/​Cargo.toml Adds heapless dependency.
native/​crates/​ring/​src/​lib.rs Exposes storage rings.
native/​crates/​ring/​src/​event.rs Adds record peeking.
native/​crates/​ld/​tests/​link_engine.rs Formats linker tests.
native/​crates/​ld/​tests/​built_images.rs Adds exact-profile image verification.
native/​crates/​ld/​src/​place.rs Formats placement tests.
native/​crates/​late/​src/​metal.rs Loads native modules through library grants.
native/​crates/​late/​src/​lib.rs Defines library admission rules and tests.
native/​crates/​driver/​src/​stor/​timeline.rs Adds bounded completion timelines.
native/​crates/​driver/​src/​stor/​mod.rs Adds storage queue abstraction.
native/​crates/​driver/​src/​stor/​grant.rs Adds storage extent grants.
native/​crates/​driver/​src/​stats.rs Counts stray completions.
native/​crates/​driver/​src/​seam.rs Adds quiet-target retirement witness.
native/​crates/​driver/​src/​ring.rs Adds queue reset methods.
native/​crates/​driver/​src/​lib.rs Exposes storage transport.
native/​crates/​driver/​src/​gpt.rs Defines pack partition type.
native/​crates/​driver/​src/​cookie.rs Adds claimed command identifiers.
native/​crates/​driver/​src/​common/​pagetable/​walker.rs Uses write-aware table resolution.
native/​crates/​driver/​src/​common/​pagetable/​alloc.rs Tracks dirty tables and accelerates lookup.
native/​crates/​driver/​src/​block/​region.rs Adds read-only region sealing.
native/​crates/​driver/​src/​block/​mod.rs Adds streaming targets and recovery interfaces.
native/​crates/​driver/​src/​block/​memory.rs Extends device double and streaming tests.
native/​crates/​driver/​src/​accel.rs Adds ordered execution and diagnostics.
native/​crates/​driver/​Cargo.toml Updates accelerator dependency.
native/​crates/​dagfs/​src/​walk.rs Exposes named-grant rights.
native/​crates/​dagfs/​src/​protocol.rs Adds storage control messages.
native/​crates/​dagfs/​src/​object.rs Defines attesting-stamp rights.
native/​crates/​dagfs/​src/​lib.rs Exposes library name and storage APIs.
native/​crates/​dagfs/​src/​io.rs Routes large reads through storage rings.
native/​crates/​dagfs/​src/​graph.rs Documents typed-creation authority.
native/​crates/​dagfs/​src/​fs.rs Adds launch-ring state and bounded status.
native/​crates/​dagfs/​src/​error.rs Adds retirement failure classification.
native/​crates/​dagfs/​src/​client.rs Adds storage lending and bounded calls.
native/​crates/​dagfs/​Cargo.toml Adds runtime ring dependency.
native/​crates/​collections/​src/​boundedvec.rs Formats test assertion.
native/​crates/​abi/​src/​uring.rs Adds discard opcode.
native/​crates/​abi/​src/​task.rs Adds launch roles and capacity.
native/​crates/​abi/​src/​stor.rs Defines storage wire vocabulary.
native/​crates/​abi/​src/​process.rs Adds interrupts and stream-host roles.
native/​crates/​abi/​src/​monitor.rs Extends fault and traffic metrics.
native/​crates/​abi/​src/​machine.rs Adds calibrated worker-width metadata.
native/​crates/​abi/​src/​lib.rs Exposes new ABI modules.
native/​crates/​abi/​src/​iommu_status.rs Adds bounded IOMMU observations.
native/​crates/​abi/​src/​image.rs Adds model-data launch profile.
native/​crates/​abi/​src/​guest/​x86_64/​mod.rs Defines guest register positions.
native/​crates/​abi/​src/​guest/​wire.rs Expands guest records and decode assistance.
native/​crates/​abi/​src/​guest/​riscv64/​mod.rs Documents unimplemented guest backend.
native/​crates/​abi/​src/​guest/​mod.rs Separates shared and architecture-specific vocabulary.
native/​crates/​abi/​src/​guest/​aarch64/​mod.rs Documents unimplemented guest backend.
native/​crates/​abi/​src/​cap.rs Adds memory-controller resource kind.
native/​Cargo.lock Synchronizes native dependencies.
docs/​lua.md Documents grant-only native loading.
crates/​lua/​src/​bridge.rs Adopts restricted loader and refusal messages.
Cargo.lock Synchronizes facade dependencies.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +86 to +88
pub fn reset(&mut self) {
self.tail = 0;
self.cycle = true;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The hazard is real in principle but no current caller reaches it. The only caller of SubRing::reset is NVMe's Qpair::reset, and those rings are always Modulo. xHCI's LinkTrb rings are never reset. This file is kore's own code exported byte-exact (tools/sync-native.py; libkore must not hand-edit native/), so the fix belongs upstream: tracked as MicroPerceptron/kore#1290 and not changed here.


Generated by Claude Code

Comment on lines +693 to +694
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Quiet<U> {
Quiet(f(self.0))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed as an API hole: map is pub and retire_quiet does not tie the proof to the buffer. The one caller (services/dagfs/src/durable.rs:614 in kore) projects correctly. Per seam.rs:677-680, a wrong proof costs a recorded IOMMU fault, not a stray write. This is kore's code exported byte-exact (libkore must not hand-edit native/), so the fix belongs upstream: tracked as MicroPerceptron/kore#1290 (typed same-allocation projection, or unsafe with an identity contract) and not changed here.


Generated by Claude Code

Comment on lines +279 to +281
fn reset(&mut self) -> bool {
self.device.reset()
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed for stor::Single, which is used only by tests. Production QueueSets already zero both fields on reset (services/dagfs/src/durable.rs:727-735 in kore). This is kore's code exported byte-exact (libkore must not hand-edit native/), and the upstream issue already exists as MicroPerceptron/kore#1210. Not changed here.


Generated by Claude Code

/// `InputReady`, and if it exits instead it exits without `Closed`. The
/// launcher revokes the task if the child leaves the record unread past
/// its grace.
Interrupt,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed, and already live on kore main: kore composes this same adapter with an ABI that has carried Interrupt since kore a2866d761. Ctrl-C on wasm <guest> currently ends the guest with stdio lost: Protocol. This PR doesn't touch crates/wasi, and the right handling is an interrupt-policy design (a distinct interrupted state wired to guest cancellation), not a one-line arm. I filed it as #28 with the evidence and a test plan rather than widen this PR.


Generated by Claude Code

.await;
None
}
Work::Recheck => None,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed. Work::Recheck only loops back, and retry_one_return_cleanup runs only from serve_return/serve_one. A deferred return therefore stays held while the host wakes every 2 ms. This is kore's code exported byte-exact (libkore must not hand-edit native/), so the fix is upstream: filed as MicroPerceptron/kore#1289, with the reachable callers and a proposed idle-retry helper. Not changed here.


Generated by Claude Code

The native resync brought kore's newer `ProviderError::Retiring` (a DMA
window an earlier client lent has not retired and the requester-wide
retirement failed), and `provider_class` matched it exhaustively, so
`kore-ffi` stopped compiling (`targets`, `host`, `miri`).  Append
`KoreProviderError::Retiring = 16`: additive, like `Timeout = 15` was —
every existing discriminant and the completion record's layout are
unchanged — map it, and regenerate `kore.h` with cbindgen 0.29.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDbTpiJFNzUJDBdjhHtXDm

Copy link
Copy Markdown
Contributor Author

Following up on the note above: the kore-ffi Retiring fix landed as 995dedb.

  • Local gates on 995dedb: make fmt test check docs owners cross miri bindings-check all pass. cross and miri were re-run after the container ran out of disk; there were no failures on the re-run.
  • CI on 995dedb: targets (x86_64/aarch64/riscv64gc), host, miri and Lockfile currency are green.
  • Still red: Advisories only. It is the wasmtime 48.0.5 advisory, which is red on alpha too; the earlier comment has the proposed fix.

The kore half (MicroPerceptron/kore#1288) pins this head.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Advisories is red on 995dedb. The failure is not this PR's, and no fix exists yet. Proposed patch below.

cargo audit --deny warnings reports 11 wasmtime advisories: RUSTSEC-2026-0353 through -0364, except -0360. They include host panics on async-lifted calls and after traps, unaligned host data from exception tags, a stack overflow dropping recursive types, and component-model handle tables with no global cap. Every one is fixed in >=48.0.6, <49.0.0 or >=49.0.3.

Why it isn't this PR's:

  • This PR does not touch wasmtime. alpha and this branch both lock wasmtime 48.0.5; the PR's lockfile diff is two unrelated lines.
  • alpha's last audit ran on 2026-10-12 (scheduled, green), before these advisories were published. The audit only re-runs on lockfile-touching pushes and on Mondays, so alpha will go red on its next audit too.
  • A re-run here would fail identically, because the advisory database is deterministic, so I have not re-run it.

Proposed patch (lockfile only). kore-wasi's wasmtime = "48.0.5" is a caret requirement and already admits the fix:

cargo update -p wasmtime --precise 48.0.6
  • What it moves: wasmtime, its internal crates and pulley from 48.0.5 to 48.0.6, and cranelift from 0.135.5 to 0.135.6. Nothing else moves.
  • Checked: cargo check -p kore-wasi --all-targets, which includes the dev-dependency build with cranelift and component-model, is clean against it.
  • Where it belongs: on alpha, so it reaches every branch. I'm not widening this PR with it.

Related: kore has the same exposure, and its gate can't see it. kore vendors patched copies of wasmtime, wasmtime-environ, wasmtime-internal-cranelift and wasmtime-internal-fiber at 48.0.5 (vendor/*/PATCHES.md). cargo audit skips path dependencies, so kore's supply-chain gate stays green while carrying the same 11 issues. I'm filing that in kore.


Generated by Claude Code

micro-perceptron added a commit that referenced this pull request Oct 16, 2026
## Why

wasmtime 48.0.5 carries eleven RUSTSEC advisories (2026-0353 through
-0364, all but -0360) in its component-model, concurrency, store and
handle-table code. The Advisories workflow (`cargo audit --deny
warnings`) refuses it on any branch cut from `alpha`. That is the only
red check on #27 ([Advisories
job](https://github.com/MicroPerceptron/libkore/actions/runs/38814613373/job/116696030801));
its build, target, entry and Miri jobs are green. 48.0.6 fixes all
eleven.

## What

- `crates/wasi/Cargo.toml`: kore-wasi's requirements on `wasmtime` (the
target dependency and the host dev-dependency) and on `wasmtime-wasi-io`
move to `48.0.6`. A caret requirement on 48.0.5 would still let a
consumer resolve the vulnerable release through this crate; 48.0.6 rules
it out.
- `Cargo.lock` moves the whole family and nothing else, 29 packages:
- `wasmtime`, `wasmtime-environ`, `wasmtime-internal-*`,
`wasmtime-wasi-io`;
  - `pulley-*`;
  - `cranelift-*` 0.135.6.
- `native/Cargo.lock` holds no Wasmtime and is unchanged.

## Verification

Local runs of the steps CI runs, all exit 0 (zig 0.16.0 for kore-ffi's
build script):
- `cargo audit --deny warnings` on `Cargo.lock` and `native/Cargo.lock`,
and lockfile currency (`--locked` resolves both).
- `make fmt test check docs owners bindings-check` and
`tools/check-local.py native`.
- Per-target `cargo check` and `tools/check-entry.py` on x86_64, aarch64
and riscv64gc.
- `make miri`.

## What this unblocks

Once this lands on `alpha`, #27 goes green on
Advisories when it picks up `alpha` (merge or rebase); nothing in that
PR needs to change.

## kore side

kore vendors Wasmtime as a `no_std` patch and was still building 48.0.5.
The kore PR (linked here once it opens) carries that patch forward to
48.0.6 and fixes why kore's own `make audit` never reported these
advisories: crates patched to a path were invisible to it.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01TmEMGSFqb56Tcsvuk9PQPx)_
@SnowCheetos
SnowCheetos merged commit 4d873c5 into alpha Oct 16, 2026
7 checks passed
@SnowCheetos
SnowCheetos deleted the ft/cool-bardeen-f86yix branch October 16, 2026 23:21
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.

4 participants