Repository navigation
issues: an image's GUIDs are drawn from the host's random source - #881
Conversation
Two stagings of one metal selection from one clean committed tree in one checkout came out with different sha256s during PR #873's metal runs. Six such pairs were diffed byte by byte, per GPT region, partition, FAT file and directory-entry field. Each pair differs in 391 to 413 bytes; kernel, loader, ROOT and LOG are identical in all six. Every differing byte is either a GUID that build/image.rs draws from gptwrite::random_guid on each call (the disk's, each partition's, /toyos/log.guid, the slot table's) with the CRCs over them, or the clock, which issues/an-images-signed-version-and-its-fat-dates-are-the-hosts-clock.md already holds. Nothing filed held the GUIDs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
b513cf6 to
b2747ed
Compare
|
Review, round 1, head Net ( Checked, no finding:
BLOCKER
NOTE
SEND BACK |
…hat ends its floor half Review round 1 of #881 (SEND BACK): - Owner: issues/toyos-builds-itself.md. Its M4 exit, a guest build of the image whose hashes match the host build of the same commit, is not met while every GUID is drawn afresh. - The exit now says what a GUID is derived from, the image's own inputs (its sections and its key), so a GUID taken from the process id, the checkout path or the host's name no longer closes it. - Stage 3 of issues/the-loader-does-only-what-must-precede-the-handover.md deletes floor::Scope and names every floor for its key alone, which ends the floor half of the log-GUID constraint; the file now says so. - The staging command names its directory: --metal-readback <dir>, which tests/metal/src/testargs.rs requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
… run -- --ci host EXIT=0
|
Review, round 2, head Net ( Round 1's findings
Checked, no finding
BLOCKER None. NOTE
LAND AFTER NAMED CHANGES |
… and attempts record among the log GUID's readers Round 2 of the review on #881 named three changes; two are this file's. Scope and exit narrowed to an image's GUIDs. `designate_data_disk` lays the scratch DATA disk `create_sparse` makes for a guest's `/apps` and `/home` (`cargo run`'s `target/nvme.img`, the harness's per-lane NVMe file), and `install` lays the disk a `Storage::Disk` test boots; both draw a DATA GUID and, through `lay`, a disk GUID, and neither disk is an image. Their only input beside the path is a length, so "a function of the image's own inputs" could not be read for them. The exit now names every GUID `create_boot_image` writes, the image's disk GUID among them. The log-GUID constraint now names every reader the loader has: - the floor's variable name (`lib/update/src/floor.rs`), ending at stage 3 of the loader track; - the log-volume lookup (`loader/src/loaderlog.rs`); - the black box's record owner (`loader/src/main.rs:685-688`, `loader/src/blackbox.rs` `harvest`), which clears another image's record instead of reporting it, and which stage 9 moves into the kernel still keyed on the log GUID; - the attempts record's owner (`loader/src/attempt.rs` `read`, `lib/update/src/record.rs` `Record::decode`), which stage 5 replaces with the slot table's tries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
… run -- --ci host EXIT=0
…ed-ruling #871 closes issues/every-syscall-saves-the-fp-state-and-every-preemption-disable-is-locked.md (cdd090b), which this branch modified: the deletion is taken. This branch's four hunks there are accounted for: the SDM §16.4 and APM §2.5.12 citations backed a save at the switch, which #871 built; the §6.6 to §7.6 correction is at PerCpu::preempt_count's doc on main; the kill line and the exit's "or kept with its refusal reason" were about an exit #871 met in full. The track, which this branch takes up, drops the closed file from its measured stages and its exit list, and drops the "Unexplained" bullet on the syscall's lock saving, which pointed at that file and which cdd090b answers by counting ten stripped sites. Its exit list gains the two issues #871 filed with the track as their owner: every-syscall-takes-the-process-table-lock-twice-to-count-itself and a-thread-resuming-on-the-cpu-that-holds-its-state-restores-it-again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
serve.rs's one conflict is its imports: #861 took `Poller` out for `watches::Watches`, and this branch added `toyos::port::Acceptor` for the badge read. Both are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…top's design branch #871 makes CR4.OSXSAVE required and gives user programs AVX state in XCR0, so std's feature detection reports AVX and FMA on a CPU that has them, and rubato's own dispatch takes AvxInterpolator on the T14 and the AMD bench. Round 3 of the design measures the resampler on that and on SseInterpolator, which rubato takes on an AVX CPU without FMA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
No conflicts. #871 moves the user FP/vector save to the switch and changes the context's identity (`runs`); this branch's kernel side touches neither: `KernelHw::kick`'s self-route sets `need_resched`, which the pass still clears before it drains (`sched::driver::pass`), so the pass this branch's kept probe asks for survives into the next poll. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Files
issues/an-images-guids-are-drawn-from-the-hosts-random-source.md. Issues only: no source, test or manifest changes.Why
PR #873's metal images were staged from committed trees. When the AMD bench's session was cut off, the judges that ran afterwards found boots missing and rebuilt those images in place. Every rebuilt image came out with a different sha256 from the one the request named, including the ones rebuilt from an unchanged tree. The orchestrator asked why. ToyOS's north star is reproducing the host's bytes.
What two stagings of one tree differ in
Method. Six pairs, each the same selection staged twice by
cargo test --test toyos-build -- --metal --metal-readback <dir>from one clean committed tree in one checkout, in two processes. Each pair was diffed byte by byte with a read-only script. The script maps every differing byte to a GPT region or partition, and inside each FAT32 volume to a file's contents or a directory-entry field. The scripts are diffs/imgdiff.py, diffs/pehdr.py and diffs/keyfind.py; diffs/commands.txt says which images each output compares, and diffs/exits.txt holds their exit codes, 0 each.d4c2f8ebescout-tlb-based4c2f8ebelatencycase9b30f5e28latencycase9b30f5e28scout-tlb-base363e0e841shared-debug363e0e841testcasesEvery differing byte has one of two sources, in all six pairs.
build/image.rstakes every GUID it writes fromgptwrite::random_guid(getrandom), drawn again on eachcreate_boot_imageandlaycall. Those bytes are the disk GUID in both GPT headers, five unique partition GUIDs in both entry arrays, the CRCs over them,/toyos/log.guidon the ESP, and slot A's two GUIDs in the slot table.version_now's signed version in/toyos/image.sigand the slot table, the signature over that version, and the FAT creation and write times (ctime,ctime_tenth,wtime) of every entry on the ESP and slot A's volume.p1, counted from its per-region totals in diffs/p1-base-latencycase.txt:
log.guid16, slot table 32. That is 254.image.sig65, slot table version 2. That is 135.Two checkouts of one commit (diffs/p6-head-two-checkouts.txt, diffs/p6-loader-pe.txt, diffs/keyfind.txt) differ further:
issues/two-checkouts-of-one-tree-build-different-guest-bytes.mdrecords.TimeDateStamp, which are not clock readings (2073 and 2066 as Unix times).A key per checkout is by design (
issues/the-machine-updates-itself-without-ubuntu.md, "Keys"), an input like the config, and is not filed.Decision: a new file, and which existing one holds the rest
issues/an-images-signed-version-and-its-fat-dates-are-the-hosts-clock.md, which namesversion_nowandbuild_time. That file is not edited.git grep -n -i guid origin/main -- issues/.issues/the-loader-does-only-what-must-precede-the-handover.mdstates that one image's sticks share their GUIDs.issues/the-anti-rollback-floor-is-a-firmware-variable.mdkeys a throwaway floor on the log GUID. Neither is about reproducing the bytes.create_boot_imagewrites.designate_data_diskandinstalldraw a DATA GUID and, throughlay, a disk GUID too, but for disks that are no image: the scratch diskcreate_sparsemakes for a guest's/appsand/home(cargo run'starget/nvme.img, the harness's NVMe file), and the disk aStorage::Disktest boots an installed image from (tests/common/qemu.rs). The scratch disk's only input beside its path is a length, so "a function of the image's own inputs" cannot be read for it. The file names both and says it does not hold them.lib/update/src/floor.rs), so that no image the key signs holds another to a floor (build/signing.rs). This ends at stage 3 ofissues/the-loader-does-only-what-must-precede-the-handover.md, which deletesfloor::Scopeand names every floor for its key alone.loader/src/loaderlog.rs).loader/src/main.rs:685-688,loader/src/blackbox.rsharvest). This does not end: stage 9 moves the check into the kernel, still keyed on the log GUID.Record::decoderefuses one naming another (loader/src/attempt.rs,lib/update/src/record.rs). This ends at stage 5, which replaces that record with the slot table's tries.issues/toyos-builds-itself.md. Its M4 exit is a guest build of the image whose hashes match the host build of the same commit, and no image whose GUIDs are drawn meets it. The file staysstatus: open, because that track is open and nobody holds it.create_boot_imagewrites, the disk GUIDlaywrites for it among them, is a function of the image's own inputs (its sections and its key), and a host test builds one image twice and finds its partition table, slot table and/toyos/log.guididentical. Stating the derivation keeps a GUID taken from the process id, the checkout path or the host's name from closing the file. The exit does not depend on the clock file, so either can close first.Gates
cargo run -- --ci host311c89a8cHost: 76 step(s), all green)No guest test is reached: the diff touches only
issues/.What I am unsure of
designate_data_diskandinstalldraw are read off the code, not measured: no metal image is either disk. The file leaves them out of its scope.git grep -n -i -E 'log_guid|log\.guid' -- tests/ build/finds onlybuild/image.rs.git grep -n -E 'floor::|floor_scope|ToyOSImageFloor|Scope::Image' -- tests/ build/finds only the key's scope handed to the loader's build (build/build.rs,build/clippy.rs,build/signing.rs). The loader reads the log GUID as the floor's name, to find the log volume, as the owner of a black-box record and as the owner of the attempts record, and the file names all four. The loader also hands it to the kernel. The supervisor claims the log partition by that GUID, and the kernel refuses a claim when two partitions carry it (system/supervisor/src/main.rs,kernel/src/gpt.rsseek). The file does not name that reader. A metal bench keeps its UEFI variables across boots, so it holds a floor under every log GUID it has booted. Whether that matters once GUIDs stop being fresh is the fix's question, and I have not answered it.🤖 Generated with Claude Code
https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy