From b2747ed30e6dfc07811df044357f86f90ba78f90 Mon Sep 17 00:00:00 2001 From: japabu Date: Mon, 12 Oct 2026 11:28:30 +0200 Subject: [PATCH 1/3] issues: an image's GUIDs are drawn from the host's random source 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 Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy --- ...-are-drawn-from-the-hosts-random-source.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 issues/an-images-guids-are-drawn-from-the-hosts-random-source.md diff --git a/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md new file mode 100644 index 0000000000..792f5aefdb --- /dev/null +++ b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md @@ -0,0 +1,44 @@ +--- +status: open +kind: defect +opened: 2026-10-12 +--- + +# An image's GUIDs are drawn from the host's random source + +Two builds of one plan write different images, so ToyOS rebuilding itself +cannot reproduce the host's bytes. Every GUID `build/image.rs` writes comes +from `gptwrite::random_guid`, the operating system's random source, drawn +again on every call: `create_boot_image` draws the log partition's, the +ESP's, the slot table's and each slot's boot and ROOT GUIDs, and writes the +log's again into the ESP's `/toyos/log.guid` and each slot's into the slot +table; `lay` draws the disk GUID of every disk it lays; `designate_data_disk` +and `install` draw the DATA partition's. + +Measured on six pairs of metal images, each pair one selection staged twice +by `cargo test --test toyos-build -- --metal --metal-readback` from one clean +committed tree in one checkout: each pair differs in 391 to 413 bytes, and +kernel, loader, ROOT and LOG are byte-identical in all six. In one pair, +254 of its 393 bytes are the GUIDs and the GPT CRCs over them, 135 are the +clock +(`issues/an-images-signed-version-and-its-fat-dates-are-the-hosts-clock.md`: +the signed version and the signature over it, and FAT entry times), and 4 +are the slot table's CRC over both. + +Two checkouts of one commit differ further, and not by anything this file +holds: in the kernel and ROOT, as +`issues/two-checkouts-of-one-tree-build-different-guest-bytes.md` records, +and in the loader, which carries two copies of its checkout's throwaway +public key. + +The log partition's GUID is what keeps a throwaway key's anti-rollback floor +per image: the floor's UEFI variable is named by it +(`lib/update/src/floor.rs`), so that no image the key signs holds another to +a floor (`build/signing.rs`), and the loader finds the log volume by it +(`loader/src/loaderlog.rs`). Whatever replaces the draw still gives two +images that differ two log GUIDs, and decides what a second build of one +image inherits from the first one's floor. + +**Exit**: no GUID `build/image.rs` writes is drawn from a random source, and +a host test builds one image twice and finds its partition table, slot table +and `/toyos/log.guid` identical. From b0671d96792d96896839c77a69c1d201b978f775 Mon Sep 17 00:00:00 2001 From: japabu Date: Mon, 12 Oct 2026 16:22:49 +0200 Subject: [PATCH 2/3] issues: the GUID file names its owner, its derivation and the stage that 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 , which tests/metal/src/testargs.rs requires. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy --- ...s-are-drawn-from-the-hosts-random-source.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md index 792f5aefdb..084a5b8baa 100644 --- a/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md +++ b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md @@ -16,8 +16,8 @@ table; `lay` draws the disk GUID of every disk it lays; `designate_data_disk` and `install` draw the DATA partition's. Measured on six pairs of metal images, each pair one selection staged twice -by `cargo test --test toyos-build -- --metal --metal-readback` from one clean -committed tree in one checkout: each pair differs in 391 to 413 bytes, and +by `cargo test --test toyos-build -- --metal --metal-readback ` from one +clean committed tree in one checkout: each pair differs in 391 to 413 bytes, and kernel, loader, ROOT and LOG are byte-identical in all six. In one pair, 254 of its 393 bytes are the GUIDs and the GPT CRCs over them, 135 are the clock @@ -37,8 +37,14 @@ per image: the floor's UEFI variable is named by it a floor (`build/signing.rs`), and the loader finds the log volume by it (`loader/src/loaderlog.rs`). Whatever replaces the draw still gives two images that differ two log GUIDs, and decides what a second build of one -image inherits from the first one's floor. +image inherits from the first one's floor. The floor half of that ends at +stage 3 of `issues/the-loader-does-only-what-must-precede-the-handover.md`, +which deletes `floor::Scope` and names every floor for its key alone. -**Exit**: no GUID `build/image.rs` writes is drawn from a random source, and -a host test builds one image twice and finds its partition table, slot table -and `/toyos/log.guid` identical. +**Owner**: `issues/toyos-builds-itself.md`, whose M4 exits on a guest build +of the image whose hashes match the host build of the same commit, which no +image whose GUIDs are drawn meets. + +**Exit**: every GUID `build/image.rs` writes 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.guid` identical. From ba8fbb17971ce5e21b31c663b18f18bea06c1449 Mon Sep 17 00:00:00 2001 From: japabu Date: Mon, 12 Oct 2026 16:47:24 +0200 Subject: [PATCH 3/3] issues: the GUID file holds an image's GUIDs, and names the black box 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 Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy --- ...-are-drawn-from-the-hosts-random-source.md | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md index 084a5b8baa..a73b62462b 100644 --- a/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md +++ b/issues/an-images-guids-are-drawn-from-the-hosts-random-source.md @@ -7,13 +7,16 @@ opened: 2026-10-12 # An image's GUIDs are drawn from the host's random source Two builds of one plan write different images, so ToyOS rebuilding itself -cannot reproduce the host's bytes. Every GUID `build/image.rs` writes comes -from `gptwrite::random_guid`, the operating system's random source, drawn -again on every call: `create_boot_image` draws the log partition's, the -ESP's, the slot table's and each slot's boot and ROOT GUIDs, and writes the -log's again into the ESP's `/toyos/log.guid` and each slot's into the slot -table; `lay` draws the disk GUID of every disk it lays; `designate_data_disk` -and `install` draw the DATA partition's. +cannot reproduce the host's bytes. Every GUID an image carries comes from +`gptwrite::random_guid`, the operating system's random source, drawn again on +every `create_boot_image` call: it draws the log partition's, the ESP's, the +slot table's and each slot's boot and ROOT GUIDs, and writes the log's again +into the ESP's `/toyos/log.guid` and each slot's into the slot table; `lay` +draws the image's disk GUID. `designate_data_disk` and `install` draw a DATA +partition's GUID the same way, and `lay` a disk GUID for each, on the scratch +disk a guest keeps `/apps` and `/home` on and on the disk a test boots an +installed image from. Neither disk is an image, and this file does not hold +them. Measured on six pairs of metal images, each pair one selection staged twice by `cargo test --test toyos-build -- --metal --metal-readback ` from one @@ -34,17 +37,26 @@ public key. The log partition's GUID is what keeps a throwaway key's anti-rollback floor per image: the floor's UEFI variable is named by it (`lib/update/src/floor.rs`), so that no image the key signs holds another to -a floor (`build/signing.rs`), and the loader finds the log volume by it -(`loader/src/loaderlog.rs`). Whatever replaces the draw still gives two -images that differ two log GUIDs, and decides what a second build of one -image inherits from the first one's floor. The floor half of that ends at -stage 3 of `issues/the-loader-does-only-what-must-precede-the-handover.md`, -which deletes `floor::Scope` and names every floor for its key alone. +a floor (`build/signing.rs`). The loader finds the log volume by it +(`loader/src/loaderlog.rs`). Its black box takes it as the owner of a record +left in memory, and clears a record another image left rather than report it +as this one's (`loader/src/main.rs`, `loader/src/blackbox.rs`). Its attempts +record on the log partition names it, and one that names another partition +is refused (`loader/src/attempt.rs`, `lib/update/src/record.rs`). Whatever +replaces the draw still gives two images that differ two log GUIDs, and +decides what a second build of one image inherits from the first one's floor. +The floor's need ends at stage 3 of +`issues/the-loader-does-only-what-must-precede-the-handover.md`, which +deletes `floor::Scope` and names every floor for its key alone, and the +attempts record's at its stage 5, which replaces that record with the slot +table's tries. The black box's does not: stage 9 moves its check into the +kernel, still keyed on the log GUID. **Owner**: `issues/toyos-builds-itself.md`, whose M4 exits on a guest build of the image whose hashes match the host build of the same commit, which no image whose GUIDs are drawn meets. -**Exit**: every GUID `build/image.rs` writes 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.guid` identical. +**Exit**: every GUID `create_boot_image` writes, the disk GUID `lay` writes +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.guid` identical.