Repository navigation
ToyOS writes its own crate where security asks, above all on a trust boundary or in the kernel; a host test reds on a kernel that resolves libc, and the owner's allocator ruling is filed - #696
Conversation
…s on a kernel that resolves libc Root CLAUDE.md's Dependencies sentence on crates now carries the owner's ruling of 2026-10-03: where security or another weighty reason asks, above all in the kernel or a decoder of untrusted input, ToyOS writes its own crate with a clear boundary, held to the no-panic track's lints and tested against hostile input; the kernel takes as few community crates as it can justify and depends on no libc. The general rule (general, widely used, used as published, no driver crate, a fork goes when upstream has it) stands unchanged. kernel/Cargo.lock names libc, windows-sys and windows-link. They are dlmalloc's target-gated edges, cfg(all(unix, not(target_arch = "wasm32"))) and cfg(target_os = "windows"); neither kernel target has a target_family (both are target_os = "none" under the stable and the fork compiler), so cargo resolves, compiles and links none of them. Measured for both targets: cargo tree -i prints nothing, the unit graph holds cfg-if, dlmalloc, hashbrown and rustc-demangle as the only registry crates, a fresh build's deps directory has no libc or windows rlib, and each kernel ELF has no undefined symbol and no needed library. A lock is platform-independent, so the entry stays as long as dlmalloc declares the edge; dlmalloc 0.2.14, the newest published, declares it unconditionally on unix. Reading the lock therefore cannot show the clause holds, and a dependency bump that widened such an edge to a none target would change no line naming libc. build::tests now asks cargo tree, per Arch::kernel(), with every kernel feature, for the kernel's normal non-proc- macro graph, and reds on libc. Negative control: the kernel given a libc dependency builds green with a libc rlib compiled in, and the test reds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
|
Evidence for f15b74c: the negative control's patch and run, and the libc measurements. Negative control: mutation-kernel-takes-libc.patchdiff --git a/kernel/Cargo.lock b/kernel/Cargo.lock
index 90c5ca15e..d17b68c2c 100644
--- a/kernel/Cargo.lock
+++ b/kernel/Cargo.lock
@@ -36,6 +36,7 @@ dependencies = [
"bcachefs",
"dlmalloc",
"hashbrown",
+ "libc",
"rustc-demangle",
"toyos-abi",
"toyos-acpi",
diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml
index b3c602b75..dbc84953d 100644
--- a/kernel/Cargo.toml
+++ b/kernel/Cargo.toml
@@ -393,3 +393,4 @@ toyos-xhci = { path = "../toyos-xhci" }
rustc-demangle = "0.1"
hashbrown = { version = "0.16", default-features = false }
dlmalloc = { version = "0.2", default-features = false }
+libc = { version = "0.2", default-features = false }mutation-run.log (apply, build, test, restore)measure-tree.logmeasure-toyos-cfg.logmeasure-unitgraph.logmeasure-x86-artifacts.logmeasure-aarch64-artifacts.logcargo-info-dlmalloc.log |
|
Review of #696 at f15b74c, round 1. Net lines:
Merge with Evidence:
BLOCKER
NOTE
REMOVE
SEND BACK |
…c test names no third-party edge Answers review round 1 of #696 (comment 5973524429). Root CLAUDE.md's crate sentence now reads: "Where security or another important reason asks, above all on a trust boundary or in the kernel, we write our own crate, with a clear boundary and well tested; the kernel takes as few community crates as it can justify and depends on no libc." f15b74c called its whole sentence the owner's ruling of 2026-10-03. It was not, and history keeps that message, so this one says where each part of the sentence comes from: - The owner's words, 2026-10-03: "if it makes sense ... due to security or other important reasons we do it" (where security or another important reason asks, we write our own crate), "a crate with a clear boundary and is well tested", "Especially in the kernel" (above all in the kernel), and "Our kernel must not depend on libc". - A formulation the orchestrator put to him, which he accepted ("Yes add a fitting rule to claudemd"): "a crate on a trust boundary or in the kernel is ours, with a clear boundary and tests, and everywhere else the ecosystem's". "On a trust boundary" is its words. It replaces f15b74c's "a decoder of untrusted input", which was neither his nor accepted by him. - Neither: "the kernel takes as few community crates as it can justify" is the brief's statement, as a rule, of his worry about community crates in the kernel. f15b74c's "held to the no-panic track's lints and tested against hostile input" was neither his words nor part of what he accepted. It is replaced by his "well tested". The libc test's doc comment drops the clause that named dlmalloc's current edge on unix. That clause would go false the day dlmalloc changes, and the reason before it already stands on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
|
Review of #696 at 24b11b6, round 2. Net lines:
The merge base is Round 1 BLOCKERs
Round 1 NOTEs and REMOVE
Evidence at 24b11b6
BLOCKER NOTE
REMOVE
LAND AFTER NAMED CHANGES |
Review round 2 of #696 (comment 5973692927), its second and third NOTEs. issues/kernel/toyos-has-its-own-allocator.md records the owner's ruling of 2026-10-03, as the orchestrator relayed it: our own allocator crate, one core with two fronts; the kernel's first, built host-first and swapped in after the three steps of the latency track; std's for programs later, after measuring against dlmalloc; and the 2 MiB heap-growth stall fixed now. No file recorded that ruling before. Its exit deletes build::tests::the_kernel_resolves_no_libc_for_either_target once dlmalloc leaves the kernel: the test sees what the lock cannot only while a kernel dependency names libc for another platform, and after dlmalloc a libc line arriving in kernel/Cargo.lock is something a reviewer reads. issues/build/the-kernels-libc-test-reads-the-host-compilers-cfg-not-the-forks.md records the gap the branch found: the test resolves with the host's compiler, stable on CI, whose host job installs no ToyOS toolchain, and the kernel builds with the fork. Measured with rustc --print cfg on both kernel targets, stable 1.98.1 against the fork's 1.99.0-dev, every run exiting 0: the fork prints every line stable does and adds more, target_feature="x87" on x86_64 among them; the two agree on target_os, target_arch and the absence of unix, which are what dlmalloc 0.2.13 gates its libc and windows-sys edges on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
|
Round 3 measurement behind Versions: x86_64-unknown-noneStable:
aarch64-unknown-none-softfloatStable:
|
src/build.rs conflicted where this branch inserts the_kernel_resolves_no_libc_for_either_target above the doc #694 rewrote for declared_model_controls. Resolved as #694's review named: this branch's test, and #694's doc ("every feature of the kernel's manifest but its builds and [`KERNEL_CARRIES`]..."). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8
What changed, and why
Root
CLAUDE.md, Dependencies: the owner's crate rulingThe owner's words, 2026-10-03:
The orchestrator then put a formulation to him: "a crate on a trust boundary or in the kernel is ours, with a clear boundary and tests, and everywhere else the ecosystem's". He answered:
The old sentence ("Only general and widely used crates — one that does our job we write ourselves, and a driver crate never; third-party crates are used as published, and a fork carries …") is replaced by two sentences. Nothing else in the file changes.
Where each part comes from:
Why the sentence keeps the owner's condition and does not state the accepted formulation as an absolute: his own words make writing our own conditional ("if it makes sense … due to security or other important reasons we do it"). The accepted formulation says where that matters most, and the sentence keeps both.
libc: locked only, never compiled or linked
kernel/Cargo.locknameslibc,windows-sysandwindows-link. Where they come from:dlmalloc0.2.13 declareslibcundercfg(all(unix, not(target_arch = "wasm32")))andwindows-sysundercfg(target_os = "windows"), andwindows-linkcomes in throughwindows-sys.Neither kernel target satisfies either
cfg.rustc --print cfgshowstarget_os="none"and notarget_familyforx86_64-unknown-noneand foraarch64-unknown-none-softfloat, under both the stable compiler and thetoyosfork compiler the kernel builds with.What was measured in round 1, for both targets:
cargo tree --locked --offline --target <t> -e all -i libc(same forwindows-sysandwindows-link)--target alllibc → dlmalloc → kernel, EXIT=0cargo +toyos build --unit-graph -Z unstable-options --profile toyos --target <t>: registry crates in the graphcfg-if,dlmalloc,hashbrownandrustc-demangleonly, EXIT=0cargo run -- --build-only, and--arch aarch64 --build-only): libc or windows artifact in the deps directoryllvm-nm -ullvm-readobj --needed-libsNeededLibraries [ ]NeededLibraries [ ]So nothing was compiled that needed removing.
The lock entry goes with
dlmalloc. The owner ruled on 2026-10-03 that the kernel'sdlmallocis replaced by our own allocator. This PR files that ruling asissues/kernel/toyos-has-its-own-allocator.md(below), whose exit removeslibc,windows-sysandwindows-linkfromkernel/Cargo.lock.A host test that sees what the lock cannot
build::tests::the_kernel_resolves_no_libc_for_either_target(src/build.rs). For eachArch::kernel()it runscargo tree --locked --all-features -e normal,no-proc-macro --target <t>onkernel/Cargo.toml. It reds if the kernel resolveslibc. It also reds if cargo fails or prints nokernelroot, so a changed output format cannot pass it vacuously.Why a check and not only a sentence:
dlmallocis in the kernel,kernel/Cargo.locknameslibcwhatever the kernel targets take. So a dependency bump that widened itslibcedge to anonetarget would change no line that nameslibc.x86_64-unknown-noneand the kernel builds green.The test goes when
dlmallocdoes:issues/kernel/toyos-has-its-own-allocator.md's exit deletes it in the pull request that removesdlmallocfrom the kernel.Where it lives: in an existing gate,
cargo run -- --ci host's "the build system" step (cargo test --lib). It costs about 0.1 s per target (/usr/bin/time, 0.11 s and 0.05 s real).What it deliberately leaves out:
windows-sysandwindows-link, because the ruling names libc only.Two issues filed
issues/kernel/toyos-has-its-own-allocator.md(track, owner the orchestrator) records the owner's allocator ruling of 2026-10-03, which no file recorded before: our own allocator crate, one core with two fronts; the kernel's first, built host-first and swapped in after the three steps ofissues/kernel/toyos-beats-linuxs-latency-on-the-t14.md; std's for programs later, after measuring againstdlmalloc; and the 2 MiB heap-growth stall fixed now. Its evidence for the stall is the code path: heap growth runspmm::alloc_page, which scans the page bitmap and zeroes 2 MiB, insideALLOCATOR.dlmalloc.lock(). Its length on the T14 is unmeasured, and the file says so. Its exit also deletes this PR's test.issues/build/the-kernels-libc-test-reads-the-host-compilers-cfg-not-the-forks.md(tooling, owner the orchestrator) records the gap this branch found: the test resolves with the host's compiler, stable on CI, whose host job installs no ToyOS toolchain, while the kernel builds with the fork. Measured (comment 5973730043):rustc --print cfgon both kernel targets, stable1.98.1against the fork's1.99.0-dev, every run EXIT=0. The fork prints every line stable prints and adds more,target_feature="x87"on x86_64 among them. The two agree ontarget_os,target_archand the absence ofunix, which are whatdlmalloc0.2.13 gates itslibcandwindows-sysedges on, so the test's verdict is the fork's today. Exit: the test resolves against the building compiler'scfg, or it is deleted withdlmalloc. The gap is recorded rather than removed: the host job has no fork compiler to ask, and asking it at kernel-build time would move the check into the build path.Checks
Negative control, rerun at 24b11b6. The patch makes the kernel take
libcdirectly (one line in each ofkernel/Cargo.tomlandkernel/Cargo.lock). It is posted as a comment on this PR. The script (mutation.sh) applied it withgit apply --check(EXIT=0) on a clean tree, then restored it withgit apply -R(EXIT=0), andgit status --porcelain --ignore-submodules=nonewas empty afterwards. Under the patch:cargo +toyos build --profile toyos --target x86_64-unknown-noneof the kernel exits 0 and compilesliblibc-18df1fdaa3158a14.rlib.cargo test --lib -- build::tests::the_kernel_resolves_no_libc_for_either_targetexits 101: "the x86_64-unknown-none kernel resolves libc", atsrc/build.rs:2777.The control has not been re-run since. b219c99 changes only two files under
issues/. The merge 33b067c takes #694'skernel/Cargo.tomlandkernel/Cargo.lock, which move the kernel's dependencies,dlmallocamong them, under[target.'cfg(target_os = "none")'.dependencies]. The test is unchanged, and the posted patch still applies at 33b067c (git apply --check, EXIT=0).Oracle. Cargo's own resolver (
cargo tree,--unit-graph) and the linked ELFs.Gates
33b067c merges
origin/main42e5fca (#694). The only conflict was insrc/build.rs. It keeps this branch'sthe_kernel_resolves_no_libc_for_either_targetand #694's doc fordeclared_model_controls, as #694's review named (comment 5973672278). Per file, this branch's changed lines againstorigin/mainare the ones it had against 932fb70.cargo test -p toyos-build --libat 33b067c: EXIT=0, "387 passed; 0 failed; 10 ignored". The new test isokat its line 145. Log:/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/cratesrule-merge/lib-test.log, withlib-test.exitandlib-test.headbeside it.cargo run -- --ci hostat 33b067c: EXIT=0, "Host: 69 step(s), all green" (the log's last line). The new test isokat its line 136. Log:/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/cratesrule-merge/ci-host.log, withci-host.exitandci-host.headbeside it. The tree was clean after it.cargo run -- --build-onlyat 24b11b6: EXIT=0. It also moved this worktree's fork checkout to the merged pina0d444933. Nothing this branch changed since then is something the image is built from. It was not run at 33b067c.CLAUDE.md, a#[cfg(test)]function and two issue files, with no kernel, userland or harness code. No guest test is added.Earlier logs:
cargo run -- --ci hostat b219c99 exited 0 ("Host: 67 step(s), all green"), in…/orch/cratesrule-named/. Round 2's are in/Users/jan/.claude/jobs/2280e09e/tmp/scratchpad/orch/cratesrule-r2/(ci-host.log,build-only.logandmutation-run.log, each with a.exitfile holding its exit code); round 1's in…/orch/cratesrule/, posted as a comment. The round 3cfgmeasurement is posted as comment 5973730043.Net lines
git diff --shortstat origin/main...HEAD: 4 files changed, 96 insertions(+), 1 deletion(-).CLAUDE.mdhas one prose line replaced.What was open, and how it closed
cfg: filed asissues/build/the-kernels-libc-test-reads-the-host-compilers-cfg-not-the-forks.md(above).🤖 Generated with Claude Code
https://claude.ai/code/session_01WcU2Dsw6mDYtwYfzVHPzM8