Repository navigation
A move names the rights it delivers: a ring and a manifest's SysCap stay where they were given - #1204
Conversation
Owner decision wanted:
|
Review of #1204 at 3cddff6, round 1Read: the commit, the whole diff, every changed file, ArchitectureThe right owner and the simplest shape. The kernel decides once ( Verified by inspection:
BLOCKER
SUGGESTION
The questions asked
Tests and evidence
Evidence checked: host log exit 1 with one red, Nothing new is verified until metal. Must be green before landing, at the head rebased onto #1200 (the rebase edits
The third defect,
|
… unchanged soundserver's bell arrives READ|WAIT, so the wait side really does go when its client's table does, as the comment beside it claimed. `RIGHTS_UNCHANGED` is `TransferEntry::UNCHANGED`: `SYS_HANDLE_DUP`'s word for the source's own set is u32::MAX where it was u64::MAX, and its two SDK wrappers are the only writers. The manual says a holder keeps a handle until it gives it up or ends. issues/a-received-handle-has-no-knowable-type.md records that it is taken up as (handle, ObjectKind) at receive, the three constraints its review set, and that event sides widen its reach. The spawn-side fixes of this round follow in the rebase onto #1200. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Response to review r1, at f05b251Blocker 1 (a manifest Suggestions:
The third defect's record now carries the plan and your three cautions. Checks at this head: |
Both moves, a message's handles and a spawn's endowments, required
TRANSFER and carried the source's rights unchanged, so every handle that
arrived by a move could be moved on: "you may map this and nobody else
may" had no spelling, and soundserver's per-client ring was re-sendable
by its client. Dup-then-move could not express it, since the move needs
the right it would have to drop.
A moved handle is now a `TransferEntry { handle, rights }` on both
paths: `SYS_MESSAGE_SEND` takes `[TransferEntry]` and a spawn's
endowment is a `SpawnEndow` carrying one. The word is the mover's own
set or a subset; a set the handle lacks is PermissionDenied and a word
that is no set InvalidArgument, with nothing moved. The table decides
it in one place (`HandleTable::rights_to_move`), and a send its
connection refuses gives each handle back with the rights it had.
`EndowEntry` stays what a child reads back.
The SDK's sends take `Moved`, which any `OwnedHandle` converts to
unchanged; `OwnedHandle::arriving_with` narrows. soundserver lends its
ring as MAP|WRITE (`SharedMemory::lend`). The SDK's spawn endows
unchanged: nothing in the tree endows less yet.
An inbox handle no longer carries TRANSFER. Its page is mapped into its
creator alone and `inbox_submit` resolves a watch's handle in the
caller's table, so a process handed a ring ran its creator's
submissions against its own handle numbers. Nothing in the tree moved
one.
The manual says a move may narrow, that moving on is a right, that an
inbox is not moved, and carries the no-revocation ruling the closed
record held.
Closes issues/a-moved-handle-is-always-re-movable.md and
issues/a-ring-handed-to-another-process-resolves-its-watches-in-the-receivers-table.md.
`moved_rights` is the guest test of both.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… unchanged soundserver's bell arrives READ|WAIT, so the wait side really does go when its client's table does, as the comment beside it claimed. `RIGHTS_UNCHANGED` is `TransferEntry::UNCHANGED`: `SYS_HANDLE_DUP`'s word for the source's own set is u32::MAX where it was u64::MAX, and its two SDK wrappers are the only writers. The manual says a holder keeps a handle until it gives it up or ends. issues/a-received-handle-has-no-knowable-type.md records that it is taken up as (handle, ObjectKind) at receive, the three constraints its review set, and that event sides widen its reach. The spawn-side fixes of this round follow in the rebase onto #1200. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Every manifest-granted SysCap arrived carrying TRANSFER, added by `syscap_rights` because an endowment could not narrow: the supervisor had to keep the right on the duplicate to move it at all. A grantee could hand its grant to a process the manifest never named, and for `rt` the receiver entered the real-time band itself. The endowment's rights word is what removes it. `syscap_rights` is now exactly what the capability arrives with, and the supervisor endows a duplicate narrowed to it. Only `dup` lets a capability leave its program, so that name is DUP|TRANSFER: handing a cap on to a child takes duplicating it and moving the duplicate. The spelling: `toyos::spawn::Spawn::endow` carries `Moved`, and std's `CommandExt::endow_narrowed` takes the rights' bits, since std's own `toyos-abi` is not its caller's. A launch's job goes with the rights it has, and one named narrowed is refused. The kernel decodes a spawn's request as `SpawnEndow`s once, in `build_child_handles`, where it read a byte window twice by hand; the size assert that tied the request to `EndowEntry` goes. The loader's boot names, which the supervisor only maps, arrive MAP alone. The two boot images keep what they had: the supervisor hands them to the file server. `moved_rights` follows #1200's `SpawnArgs`. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
f05b251 to
23f692c
Compare
Review r1, the spawn-side half: head 23f692cRebased onto Blocker 1, fixed.
New, asked by the orchestrator: Rebase resolutions: Checks at this head: full |
Review of #1204 at 23f692c, round 2 (focused)Read: ArchitectureRound 1's blocker is fixed in the right place. The manifest's set is now exactly what arrives, the supervisor stops compensating for an endowment that could not narrow, and the workaround's BLOCKER
SUGGESTION
The questions asked
Tests and evidenceNo test is owed for the supervisor's narrowed endowment. Each link already has a detector. Evidence checked. Host log: exit 1, 1 of 110 steps red, Still unverified until metal, as the body says. Must be green before landing, on the images staged at 23f692c:
SEND BACK |
…aches its program Two doc sentences still said the supervisor hands a program its SysCap as a narrowed duplicate. It takes a plain duplicate and the endowment narrows it, and a narrowed duplicate would have to keep TRANSFER to be endowed at all. Comments only, at the same line count. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Orchestrator, before queueing at 6469b0d.
Queueing. |
Problem
Two of the open
severity: [security]handle-model defects, both read against main and true there:SYS_MESSAGE_SENDand a spawn's endowment, neededTRANSFERon the handle and carried its rights unchanged, so everything that arrived by a move could be moved on. "You may map this and nobody else may" had no spelling. soundserver's per-client ring was re-sendable by its client, and every manifest-grantedSysCaparrived carryingTRANSFERbecause the supervisor could not endow it otherwise.TRANSFER; its page is mapped into its creator alone andinbox_submitresolves a watch's handle in the caller's table.Resulting behavior
TransferEntry { handle, rights }on both paths:SYS_MESSAGE_SENDtakes[TransferEntry], and a spawn's endowment is aSpawnEndowcarrying one. The word is the mover's own set (TransferEntry::UNCHANGED) or a subset. A set the handle lacks isPermissionDenied, a word that is no setInvalidArgument, with nothing moved.HandleTable::rights_to_movedecides it for both; a send the connection refuses gives each handle back with the rights it had.EndowEntrystays what a child reads back;SpawnEndowis the request, which the kernel decodes once as that type.SysCaparrives with exactly its row's rights.syscap_rightsno longer addsTRANSFER, and the supervisor endows a duplicate narrowed to the set. Onlyduplets a capability leave its program, and it is nowDUP|TRANSFER: handing a cap to a child takes both.Movedis a handle and what it arrives with; anyOwnedHandleconverts unchanged andOwnedHandle::arriving_withnarrows.Connection::send_movedandtoyos::spawn::Spawn::endowtake it; std hasCommandExt::endow_narrowed.SharedMemory::lendis a region for one peer (MAP|WRITE): soundserver's ring, whose bell arrivesREAD|WAIT.TRANSFER, so a ring never leaves the process that made it. Nothing in the tree moved one.MAPalone.Decisions worth a reviewer's eye
docs/src/architecture/authority.md): its bullet said "a move carries the rights unchanged" while its own diagram said "unchanged or narrowed". It now says a move may narrow, that moving on is itself a right, that an inbox is not moved, and that nothing takes a handle back from a running process, the ruling whose only home was the record this closes.dupnow meansDUP|TRANSFER. WithTRANSFERgone from every other set, a row namingdupcould duplicate its cap and move the copy nowhere. The test estate is its only holder.CommandExt::endow_narrowedtakes the rights as bits and panics on a bit no right uses. std'stoyos-abiis the sysroot's and not its caller's, so the type cannot cross.Invalid: the job travels in a message to the launcher, and nothing needs it narrowed.send_movedstays beside the*_withsends. Takingimpl Into<Moved>in the six was tried first and stops existing callers inferring (lib/blockserve/src/sessions.rs:207, E0283).RIGHTS_UNCHANGEDisTransferEntry::UNCHANGED, soSYS_HANDLE_DUP's word for "unchanged" isu32::MAXwhere it wasu64::MAX.issues/a-received-handle-has-no-knowable-type.md. It is taken up as its own PR after this lands ((handle, ObjectKind)at receive); its record carries that and the review's three constraints.Tests
moved_rights(new,tests/guest/rust-tests) is a kernel-boundary test: what a handle carries is observable only by what its holder's syscalls are refused, and the endowment arm needs a second process. It is a shared-boot member, so it runs on the metaltestcasesboot; the QEMU profile runs no shared member. Arms, each judged alone so one red names every claim that broke:WRITEalone writes, and can be neither duplicated nor moved; sent unchanged it moves again;Host:
toyos-abitests the word's decoding, andtoyos-manifestthat no name butdupgives a setTRANSFERorDUP. The supervisor's narrowed endowment needs no test of its own, since each link has a detector.syscap_rights' unit test pins the set, andmoved_rightsarm 4 pins that an endowment arrives with what it named. A silent failure to narrow in the std or SDK path would leave the cap with the supervisor's whole set, andtest_rs_endowment_deniedontestcasesreds on that: the estate's row names nort, and the test asserts its cap cannot enter the real-time band. A set the cap lacked would refuse the spawn, which every boot shows.Evidence
All at 23f692c, rebased onto
origin/main2ec4ad9. The head, 6469b0d, differs from it by two doc comments (review r2), at the same line count, so no check is rerun and the staged images stand.cargo run -- --ci host(macOS)the build system; its failure list isllvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_keyand thellvm::tests::keyed_and_builtit reruns, the macOS defect inissues/the-llvm-environment-test-breaks-git-on-macos.md.clippy, warnings denied: clean. logcargo run -- --build-onlycargo test --test toyos-build -- --metal --listguest-rowsrun 42987228938:session_lifecycle a_launch_gives_each_unsent_stdio_slot_a_null a_spawn_from_an_image_frees_it_when_the_child_ends libc_children virt_smp virt_jobs_at_el2testcasesandshared-debug, whole, on the T14, judged from a tree at 23f692cmoved_rightsmoved_rights: red:line. Mutant A names arms 1, 2, 4, 5 as predicted. Mutant B names arms 1 and 3, not 3 alone (below). A, BNo Linux host run exists: the PR's own checks are skipped while it is a draft, and the macOS run cannot clear the one red step.
What the metal boots show. On
testcases:test_rs_moved_rightsexit 0 with all five claim lines andmoved_rights: ok;test_rs_endowment_denied,test_rs_messages_are_whole,test_rs_abuse_handle_table,test_rs_abuse_inbox,test_rs_audio_tone,test_rs_audio_tone_resampledandtest_rs_cpal_drop_unreleasedexit 0. Onshared-debug:test_rs_handle_lifetime,test_rs_spawn_child_ends_first,test_rs_spawn_lands_claimedandtest_rs_spawn_returns_the_censusexit 0, and no member ended nonzero.The reds on
testcases, and why none is this change's:test_rs_served_file_offset(exit 101,served_file_offset.rs:124) assertsHelper::spawn(None)answersSyscall(InvalidArgument). On main at 2ec4ad9 it answersRefused::Invalidbefore any syscall (sdk/toyos/src/spawn.rs:207). This branch touches neither line. A defect on main, unrecorded.206_libc_refusals(exit 1) printssysconf _SC_ARG_MAX: 2093056against an expected65536._SC_ARG_MAXistoyos::startup::MAX_BLOCKon main since A child's arguments and environment are memory its parent lays out #1200 and the.expectwas not updated. This branch touches neither. A defect on main, unrecorded.i219_messages_on_its_msi_vector: "no frame arrived on a message under traffic", which isissues/i219-msi-passes-only-when-the-network-sends-it-a-frame.md.idle_entered,amdvi_translates_the_boot_controller,amdvi_remaps_the_boot_controller,amdvi_usbd_drives_its_own_entry: AMD-bench rows, taken because the boot was judged whole on the T14 ("this row runs on the AMD bench";usbd_spare: the function has no MSI-X capability).console_uart_drivenis red on that same binary's panic line.boot.testcases.back_secs124 against 50 recorded, ceiling 100. The boot's own work ended at 67 s of uptime with all 256 jobs; the rest is the bench's turnaround of a 521 MB image. I have no baseline of a wholetestcasesboot to compare, so this one is unattributed, not cleared.test_rs_wake_onto_busyexit 49 is a measurement, as its registration says."No member newly red" is argued by cause, not by a same-day baseline of main, which I do not have.
Mutant B reds arm 1 as well as arm 3, where the review and I both predicted 3 alone. Arm 1 panics
a send narrowed to WRITE: PermissionDenied. A first send on a connection with no frames is refusedUnsent::Claimbysend_nowafter the handles are taken, they are given back, and the send commits through a claim after checking them again. Without the restore the handle comes back narrowed, withoutTRANSFER, and the second check refuses it. So the restore is exercised by an ordinary narrowed send, not only by a refused one, and arm 1 detects its loss too. The control is red for the mutation it names; the prediction was wrong, not the test.Unresolved
test_rs_served_file_offsetand206_libc_refusals, both from A child's arguments and environment are memory its parent lays out #1200's side and neither recorded. Not fixed or filed here.back_secstiming above is unattributed.boot:testcases, which also takes a row needing the unruntestcases-watchdogboot, so the harness restaged and rewrote the two branchimage.imgfiles after they had booted. The readbacks were not touched (their times precede it) and the judge reads only them, but the booted image bytes are no longer on disk to compare.TRANSFERand dropped to a held handle by the child's SDK. The review judged it no defect; the rights word would let the spawn do it.🤖 Generated with Claude Code