← board

Rung 3 — the image

The userland exists and is proven:

tools/busybox_diff.sh --separate --applets "$(busybox --list)"
  ORACLE  gcc separate build, 265 objects (387 cases)
  PASS    x86_64   byte-identical to the gcc oracle over 387 cases

(This ticket was filed against the 80-applet / 149-object / 261-case run. feature-c-corpus-busybox-141-applets-linked met a strictly larger bar the same day -- 141 applets, 265 TUs, no -Wl,-z,muldefs, and the gcc build itself agreeing with upstream's own separately-linked binary. The userland this rung needs is therefore bigger than the one it was written for, not smaller.)

Nothing about that is a chroot claim. It is 149 objects linked into one multiplexer that answers exactly as a gcc-built one does over 261 input cases. What it has never done is come up as PID 1 under a real kernel, which is the whole point of the rung: every proof so far runs under the host's kernel, and qemu-user at that.

The decision this rung opens with

Fetch a kernel or build one. Building is a large job and teaches nothing about pxx; fetching is a download and a version to pin. Take the measurement first — how long does a make defconfig bzImage actually take on plexus, and is there a distribution kernel small enough to boot with a busybox initramfs unmodified? Decide from those two numbers, not from taste.

Do the x86-64 image FIRST even though the cross axis is the interesting one: /dev/kvm is present, so the loop is seconds rather than minutes, and every mistake made here is one not made twice.

What the rung must prove, and what would fake it

What is NOT in this rung

Met, 2026-09-04 — what was run and what it proves

PXX=stable_linux_amd64/default/pinned tools/mkkiosk.sh \
    --busybox=<pxx-built busybox> --cases=<busybox_diff --keep work dir>

  cases: 258 applets, extracted from tools/busybox_diff.sh (a77c58d815bc)
  image: kernel 12M + initramfs 36M
    PID 1   sha256 ab28159146a5 == the busybox we built
    CONTROL cmp rejects a one-byte mutation of the same transcript
    PASS    in-guest transcript byte-identical to the host gcc oracle over 621 cases
  KIOSK-BUSYBOX-COMPLETE

Which kernel, since the ticket asks: Alpine v3.21 netboot vmlinuz-virt, 6.12.81-0-virt, fetched. The fetch-versus-build decision was already taken and measured on 2026-08-30 and this rung did not reopen it.

PID 1 is ours, asserted rather than described. /init is a script, so PID 1's exe is the interpreter — our busybox. The guest hashes /proc/1/exe itself and the host compares that to the binary it shipped, so the claim fails loudly if the image is ever built from something else.

The transcript is compared, and the comparison can fail. A cmp of two transcripts is exactly the instrument this repo warns about — it prints PASS over two names for one file just as happily — so the run flips one byte of the guest transcript and requires cmp to reject it before it will report the real result.

And with --selfhost, the owner's whole sentence runs on our own userland. --busybox --selfhost reaches SELF-HOST FIXEDPOINT INSIDE THE VM: stage1 == stage2 in a VM where PID 1, the shell, and every tool are pxx-built — seeded by the pinned v403 compiler against HEAD's compiler.pas. Previously that fixedpoint ran under DEBIAN's busybox, so the compiler was the only pxx thing in the image.

That verdict is cmp, from the binary I had just found a miscompile in, so it was positive-controlled before being believed: our busybox's cmp -s on two identical 10.2 MB files (a stage binary's size) returns 0, and returns 1 when they differ in the LAST byte only. It is not a cmp that always agrees.

Separately: the same run also boots the ordinary kiosk image on our busybox (--busybox without --cases): our busybox mounts /proc, /sys and /dev, the in-VM pxx compiles and runs a Pascal program, and the kiosk app answers sum, primes and about. That is rung 3's "boot to a userland" half; the case list is its "compared, not eyeballed" half.

Three things the host's busybox gave for free and ours does not

All three are busybox CONFIG artifacts, not pxx defects, and all three are handled in tools/mkkiosk.sh with the reason written next to the code:

What this rung could NOT see, and it matters

516 of the 621 cases are applet --help. run_dispatch_cases runs every applet twice, by argv[0] and through the multiplexer, and --help prints a string literal. The remaining 105 cases exercise cat, echo, ash and a coreutils set with real arguments — which is why the corpus is a real oracle at all — but no widening of the APPLET list reaches behaviour that --help does not touch.

Booting the thing found one such bug within a minute: uname -a printed Linux eight times, because busybox reads struct utsname through a static const unsigned short utsname_offset[] = { offsetof(...), ... } and every offset was zero. [[bug-c-offsetof-in-a-static-array-initializer-folds-to-zero-silently]] — filed, reduced to a three-line repro, and NOT fixed here: Track B does not rebuild the compiler.

That is the argument for the next rung, and it is a measurement rather than a preference: running applets with arguments found a silent wrong-value miscompile that 400 objects and 621 green cases did not.

Cite frankc-af's instance rather than this one — it is strictly stronger. [[feature-c-corpus-busybox-394-applets]] (fd456ed89, the section headed "AND THAT GREEN IS THE MOST IMPORTANT NEGATIVE RESULT ON THIS TICKET"): 374 applets, 506 objects, 853 cases byte-identical to the gcc oracle, GREEN — on the same binary whose uname -a printed Linux eight times. A wider, greener corpus, equally blind, with the binary sha and the uname --help / uname -a pair side by side. The 141 → 258 → 374 progression is the demonstration: raising the applet count is the obvious response to "516 of 621 cases are --help", it was tried twice, and it buys nothing this defect class can be seen from.

frankD landed the answer as d0104ec8e — a real-argument case group, RED on purpose at the time — and turned up two constraints doing it: nothing in a differential transcript may print its own argv[0] (three install dirs produced two correct usage messages naming different paths, and the harness reported "the two oracles disagree" with both being gcc builds of one source), and determinism excludes mtimes, not just clocks.

Log