fix(arm64): tr -d '[:space:]' is parsed as literal char-set by busybox 1.30.1
Some checks failed
CI / Go Tests (push) Successful in 1m39s
CI / Shellcheck (push) Failing after 44s
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Failing after 1m13s
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Failing after 1m31s

Ubuntu's busybox-static 1.30.1 (which we use for the ARM64 rootfs after
piCore64's BusyBox crashes in QEMU virt) doesn't recognize POSIX character
classes. `tr -d '[:space:]'` is interpreted as "delete any of the literal
characters [, :, s, p, a, c, e, ]" — so every s/p/a/c/e in module names and
sysctl keys gets eaten.

Symptoms in the boot log:
  virtio_net  -> virtio_nt   (e dropped)
  overlay     -> ovrly       (e, a dropped)
  bridge      -> bridg       (e dropped)
  nf_conntrack -> nf_onntrk  (c, a, c dropped)
  net.bridge.bridge-nf-call-iptables -> nt.bridg.bridg-nf-ll-itbl

Fix: use explicit whitespace chars `tr -d ' \t\r\n'` in both
30-kernel-modules.sh and 40-sysctl.sh. Works under any tr implementation.

Also: filter functions.sh out of the init.d stage-copy loop. It's a shared
library (sourced by init.sh), not a numbered stage. With it in init.d the
main loop runs it as a stage after stage 90, then panics with "Init
completed without exec'ing KubeSolo".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 16:02:21 -06:00
parent 31aac701db
commit 1de36289a5
3 changed files with 16 additions and 4 deletions

View File

@@ -84,10 +84,15 @@ if [ "$INJECT_ARCH" = "arm64" ] && [ -x /bin/busybox ]; then
fi fi
fi fi
# Init stages # Init stages — copy NN-name.sh files only. functions.sh is a shared library
# (sourced by init.sh proper), not a numbered stage; if it ends up in init.d
# the main loop will try to run it as a stage and fail.
mkdir -p "$ROOTFS/usr/lib/kubesolo-os/init.d" mkdir -p "$ROOTFS/usr/lib/kubesolo-os/init.d"
for stage in "$PROJECT_ROOT"/init/lib/*.sh; do for stage in "$PROJECT_ROOT"/init/lib/*.sh; do
[ -f "$stage" ] || continue [ -f "$stage" ] || continue
case "$(basename "$stage")" in
functions.sh) continue ;;
esac
cp "$stage" "$ROOTFS/usr/lib/kubesolo-os/init.d/" cp "$stage" "$ROOTFS/usr/lib/kubesolo-os/init.d/"
chmod +x "$ROOTFS/usr/lib/kubesolo-os/init.d/$(basename "$stage")" chmod +x "$ROOTFS/usr/lib/kubesolo-os/init.d/$(basename "$stage")"
done done

View File

@@ -16,7 +16,11 @@ while IFS= read -r mod; do
case "$mod" in case "$mod" in
'#'*|'') continue ;; '#'*|'') continue ;;
esac esac
mod="$(echo "$mod" | tr -d '[:space:]')" # NOTE: do NOT use tr -d '[:space:]' — Ubuntu's busybox-static 1.30.1 (used
# in the ARM64 rootfs override) doesn't parse POSIX char classes and treats
# them as a literal set, deleting [, :, s, p, a, c, e, ]. Use explicit
# whitespace chars instead so the same script works under any tr.
mod="$(printf '%s' "$mod" | tr -d ' \t\r\n')"
if modprobe "$mod" 2>/dev/null; then if modprobe "$mod" 2>/dev/null; then
LOADED=$((LOADED + 1)) LOADED=$((LOADED + 1))
else else

View File

@@ -8,8 +8,11 @@ for conf in /etc/sysctl.d/*.conf; do
case "$key" in case "$key" in
'#'*|'') continue ;; '#'*|'') continue ;;
esac esac
key="$(echo "$key" | tr -d '[:space:]')" # NOTE: do NOT use tr -d '[:space:]' — see 30-kernel-modules.sh for the
value="$(echo "$value" | tr -d '[:space:]')" # rationale. Use explicit whitespace chars so this works under
# Ubuntu's busybox-static tr too.
key="$(printf '%s' "$key" | tr -d ' \t\r\n')"
value="$(printf '%s' "$value" | tr -d ' \t\r\n')"
if [ -n "$key" ] && [ -n "$value" ]; then if [ -n "$key" ] && [ -n "$value" ]; then
sysctl -w "${key}=${value}" >/dev/null 2>&1 || \ sysctl -w "${key}=${value}" >/dev/null 2>&1 || \
log_warn "Failed to set sysctl: ${key}=${value}" log_warn "Failed to set sysctl: ${key}=${value}"