bootstrap: busybox reproducible — fixes destapados por la verificación de Stage 2
La verificación de reproducibilidad de Stage 2 (dos builds + diff de bytes) probó que musl reconstruye bit-idéntico pero busybox NO, y cazó dos no-determinismos: 1. Config interactiva: tras editar .config, silentoldconfig prompea por opciones NEW leyendo stdin → set de applets variable (build no-determinista y flaky). Fix en busybox.toml: `yes '' | make oldconfig` (defaults, determinista; 1.36.1 no tiene olddefconfig). 2. Headers UAPI del kernel: el config determinista habilita console-tools, que exige linux/kd.h (zig no la bundlea). Fix: linux-headers en bootstrap-devfs.sh (zig cc nativo la halla en /usr/include). Con ambos, musl y busybox reconstruyen bit-idéntico. Runbook §8b documenta la verificación y deja pendiente: reproducibilidad de los componentes Rust y el rebuild dentro de un builder rootfs (auto-alojamiento pleno). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
79ad2cad69
commit
01d5a02b4d
@@ -235,6 +235,35 @@ Detecta la muerte **con su `ExitStatus`** (`Killed(SIGTERM)`), programa el resta
|
||||
que [ADR 0007](../adr/0007-arje-como-init-propio.md) prometía y la Fase 5 había diferido. Exponerlo
|
||||
a la capa de IA por `agent.sock` es B.2 (bus único).
|
||||
|
||||
## 8b. Stage 2 — verificación de reproducibilidad (pre-rebuild-in-rootfs)
|
||||
|
||||
El `stage2` de hammer ancla el **content-hash** (`ArtifactHash::of_tree`, los bytes reales) del
|
||||
rootfs y lo compara con un rebuild. El rebuild **dentro** del rootfs usando *sólo* las herramientas
|
||||
de Stage 1 (auto-alojamiento pleno) necesita un **builder rootfs** — el Stage 1 mínimo es un
|
||||
*runtime* (no trae zig/make/cargo), así que ese paso es un hito aparte. Lo que **sí** se verificó
|
||||
acá: la **bit-reproducibilidad del build** (dos builds independientes del mismo componente →
|
||||
`diff -r`):
|
||||
|
||||
| Componente | Reproducible | Notas |
|
||||
|---|---|---|
|
||||
| **musl** 1.2.5 | ✅ byte-idéntico | el build C con zig cc es determinista de fábrica |
|
||||
| **busybox** 1.36.1 | ✅ tras dos fixes | (ver abajo) |
|
||||
| hammerd / arje-zero (Rust) | ☐ pendiente | rust bit-reproducible es más duro; el rebuild de arje-zero es caro (monorepo) |
|
||||
|
||||
**La verificación cazó dos no-determinismos reales en busybox** (justo lo que [SDD 09 §2](../09-trust-model.md) pide):
|
||||
|
||||
1. **Config interactiva.** Tras editar `.config`, el compile corre `silentoldconfig`, que ante
|
||||
opciones NEW (WERROR, etc.) **prompea leyendo stdin** → el set de applets salía distinto por
|
||||
corrida (build no-determinista *y* flaky). Fix: `yes '' | make oldconfig` (acepta defaults,
|
||||
determinista; busybox 1.36.1 no tiene `olddefconfig`).
|
||||
2. **Headers del kernel.** Con el config determinista, los applets de `console-tools` exigen
|
||||
`linux/kd.h` (UAPI) que zig **no** bundlea → `linux-headers` en el lab (`bootstrap-devfs.sh`);
|
||||
zig cc nativo los encuentra en `/usr/include`.
|
||||
|
||||
Con ambos, `musl` y `busybox` reconstruyen **bit-idéntico**. El próximo paso de Stage 2 es el
|
||||
rebuild *dentro* de un builder rootfs y, antes, verificar/forzar la reproducibilidad de los
|
||||
componentes Rust.
|
||||
|
||||
## 9. Cross-check opcional — `arje-packager`
|
||||
|
||||
arje trae su propio empaquetador (`03_ukupacha/arje/init/arje-packager`):
|
||||
|
||||
@@ -31,7 +31,13 @@ link = "static"
|
||||
# `zig cc`, manteniendo la hermeticidad zig-only (ADR 0003) sin meter gcc al rootfs.
|
||||
# El link final asume GNU ld y pasa flags que `zig cc` valida y rechaza (`--warn-common`, `-Map`,
|
||||
# `--verbose`); los quitamos de scripts/trylink. Es la incompatibilidad GNU-ld↔zig/lld esperada.
|
||||
configure = "make CC='zig cc' HOSTCC='zig cc' defconfig && sed -i -e 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' -e 's/^CONFIG_TC=y/# CONFIG_TC is not set/' -e 's/^CONFIG_FEATURE_TC_INGRESS=y/# CONFIG_FEATURE_TC_INGRESS is not set/' .config && sed -i -e 's/-Wl,--warn-common//g' -e 's/-Wl,-Map,[^ ]*//g' -e 's/-Wl,--verbose//g' scripts/trylink"
|
||||
#
|
||||
# `yes '' | make oldconfig` tras editar .config: sin esto, el compile corre `silentoldconfig`, que
|
||||
# al ver opciones NEW (p.ej. WERROR) **prompea interactivamente** leyendo stdin — build
|
||||
# no-determinista y flaky (lo destapó la verificación de reproducibilidad de Stage 2). `yes ''`
|
||||
# acepta el default de cada NEW ⇒ config resuelta y determinista (busybox 1.36.1 no tiene el target
|
||||
# `olddefconfig`, así que usamos `oldconfig` alimentado por `yes`).
|
||||
configure = "make CC='zig cc' HOSTCC='zig cc' defconfig && sed -i -e 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' -e 's/^CONFIG_TC=y/# CONFIG_TC is not set/' -e 's/^CONFIG_FEATURE_TC_INGRESS=y/# CONFIG_FEATURE_TC_INGRESS is not set/' .config && yes '' | make CC='zig cc' HOSTCC='zig cc' oldconfig && sed -i -e 's/-Wl,--warn-common//g' -e 's/-Wl,-Map,[^ ]*//g' -e 's/-Wl,--verbose//g' scripts/trylink"
|
||||
compile = "make -j\"$(nproc)\" CC='zig cc' HOSTCC='zig cc'"
|
||||
# busybox instala en CONFIG_PREFIX (no DESTDIR): bin/busybox + symlinks de cada applet.
|
||||
install = "make CC='zig cc' HOSTCC='zig cc' CONFIG_PREFIX=/out install"
|
||||
|
||||
@@ -113,7 +113,11 @@ else
|
||||
# y Alpine no trae ese std (no hay rustup). Falta resolver el toolchain Rust del lab (plan C.2)
|
||||
# — ver docs/runbooks/stage1-vm-boot.md §8. Hasta entonces, los componentes C (musl, busybox)
|
||||
# sí construyen end-to-end.
|
||||
NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils rust cargo"
|
||||
# `linux-headers`: UAPI del kernel (linux/kd.h, etc.) que zig cc NO bundlea; busybox y otros
|
||||
# paquetes la necesitan. zig cc nativo la encuentra en /usr/include. (Lo destapó la
|
||||
# verificación de reproducibilidad de Stage 2: con el config determinista, los applets de
|
||||
# console-tools la exigen.)
|
||||
NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils rust cargo linux-headers"
|
||||
missing=""
|
||||
for pkg in $NEEDED; do
|
||||
# apk info -e devuelve el paquete si está instalado, vacío si no.
|
||||
|
||||
Reference in New Issue
Block a user