fix(arm64): override piCore64's BusyBox with host's static busybox
Some checks failed
CI / Go Tests (push) Successful in 1m26s
CI / Shellcheck (push) Failing after 36s
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Failing after 1m15s
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Failing after 1m14s

piCore64 v15.0.0 ships BusyBox built with ARM instructions that QEMU virt
cannot emulate even under -cpu max — applets like mkdir, uname, readlink
SIGILL on first invocation (el0_undef in the panic trace). mount works
because piCore's busybox.suid happens to use a different code path.

Fix: when building the arm64 rootfs, replace piCore's bin/busybox and
bin/busybox.suid with /bin/busybox from the build host (Ubuntu's
busybox-static, statically linked, built for generic ARMv8-A).

Also add busybox-static to Dockerfile.builder so the Docker-based build
flow has the same fallback available.

Long-term: source a known-good ARM64 BusyBox build (Alpine, or our own
from upstream BusyBox) so we don't depend on the build host's package
manager. Tracked as future work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 15:38:05 -06:00
parent dc48caa959
commit 06e12a79bd
2 changed files with 21 additions and 0 deletions

View File

@@ -64,6 +64,26 @@ cp "$PROJECT_ROOT/init/init.sh" "$ROOTFS/init"
chmod +x "$ROOTFS/init"
echo " Installed staged init at /init and /sbin/init"
# --- 2b. BusyBox override for ARM64 ---
# piCore64 v15's BusyBox is dynamically linked and uses ARM instructions that
# QEMU virt cannot emulate even with -cpu max, causing applets (mkdir, uname,
# etc.) to SIGILL. Replace with the host's statically-linked busybox-static
# package, which is built for generic ARMv8-A and runs anywhere.
#
# On x86 builds this isn't an issue (TC's BusyBox works fine on QEMU x86).
if [ "$INJECT_ARCH" = "arm64" ] && [ -x /bin/busybox ]; then
if file /bin/busybox 2>/dev/null | grep -q 'statically linked'; then
cp /bin/busybox "$ROOTFS/bin/busybox"
# busybox.suid is used by mount/su/etc. Same binary; suid bit applied
# separately. We don't need suid for our use (init runs as PID 1 / uid 0).
cp /bin/busybox "$ROOTFS/bin/busybox.suid"
chmod +x "$ROOTFS/bin/busybox" "$ROOTFS/bin/busybox.suid"
echo " Replaced piCore BusyBox with host's static busybox ($(du -h /bin/busybox | cut -f1))"
else
echo " WARN: /bin/busybox on host is not static; piCore BusyBox kept (may crash in QEMU virt)"
fi
fi
# Init stages
mkdir -p "$ROOTFS/usr/lib/kubesolo-os/init.d"
for stage in "$PROJECT_ROOT"/init/lib/*.sh; do