Files
kubesolo-os/build/scripts/extract-core.sh
Adolfo Delorenzo efc7f80b65
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
feat: add security hardening, AppArmor, and ARM64 Raspberry Pi support (Phase 6)
Security hardening: bind kubeconfig server to localhost, mount hardening
(noexec/nosuid/nodev on tmpfs), sysctl network hardening, kernel module
loading lock after boot, SHA256 checksum verification for downloads,
kernel AppArmor + Audit support, complain-mode AppArmor profiles for
containerd and kubelet, and security integration test.

ARM64 Raspberry Pi support: piCore64 base extraction, RPi kernel build
from raspberrypi/linux fork, RPi firmware fetch, SD card image with 4-
partition GPT and tryboot A/B mechanism, BootEnv Go interface abstracting
GRUB vs RPi boot environments, architecture-aware build scripts, QEMU
aarch64 dev VM and boot test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:08:17 -06:00

170 lines
5.3 KiB
Bash
Executable File

#!/bin/bash
# extract-core.sh — Extract Tiny Core Linux rootfs from ISO
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CACHE_DIR="${CACHE_DIR:-$PROJECT_ROOT/build/cache}"
ROOTFS_DIR="${ROOTFS_DIR:-$PROJECT_ROOT/build/rootfs-work}"
# shellcheck source=../config/versions.env
. "$SCRIPT_DIR/../config/versions.env"
EXTRACT_ARCH="${TARGET_ARCH:-amd64}"
# Clean previous rootfs
rm -rf "$ROOTFS_DIR"
mkdir -p "$ROOTFS_DIR"
# =========================================================================
# ARM64: piCore64 .img.gz extraction (SD card image, not ISO)
# =========================================================================
if [ "$EXTRACT_ARCH" = "arm64" ]; then
PICORE_IMG="$CACHE_DIR/$PICORE_IMAGE"
if [ ! -f "$PICORE_IMG" ]; then
echo "ERROR: piCore64 image not found: $PICORE_IMG"
echo "Run 'TARGET_ARCH=arm64 make fetch' first."
exit 1
fi
echo "==> Extracting piCore64 image: $PICORE_IMG"
# Decompress .img.gz to raw image
PICORE_RAW="$CACHE_DIR/piCore-${PICORE_VERSION}.img"
if [ ! -f "$PICORE_RAW" ]; then
echo " Decompressing..."
gunzip -k "$PICORE_IMG" 2>/dev/null || \
zcat "$PICORE_IMG" > "$PICORE_RAW"
fi
# Mount the piCore rootfs partition (partition 2 in the SD image)
# Use losetup to find the partition offset
IMG_MNT=$(mktemp -d)
echo " Mounting piCore rootfs partition..."
# Get partition 2 offset (piCore layout: boot=p1, rootfs=p2)
OFFSET=$(fdisk -l "$PICORE_RAW" 2>/dev/null | awk '/^.*img2/{print $2}')
if [ -z "$OFFSET" ]; then
# Fallback: try sfdisk
OFFSET=$(sfdisk -d "$PICORE_RAW" 2>/dev/null | awk -F'[=,]' '/start=/{print $2; exit}' | tr -d ' ')
fi
if [ -z "$OFFSET" ]; then
echo "ERROR: Could not determine partition offset in piCore image"
fdisk -l "$PICORE_RAW" || true
exit 1
fi
BYTE_OFFSET=$((OFFSET * 512))
mount -o loop,ro,offset="$BYTE_OFFSET" "$PICORE_RAW" "$IMG_MNT" || {
echo "ERROR: Failed to mount piCore rootfs (need root for losetup)"
exit 1
}
# Find initramfs in the piCore rootfs
COREGZ=""
for f in "$IMG_MNT"/boot/corepure64.gz "$IMG_MNT"/boot/core.gz "$IMG_MNT"/*.gz; do
[ -f "$f" ] && COREGZ="$f" && break
done
if [ -z "$COREGZ" ]; then
echo "ERROR: Could not find initramfs in piCore image"
echo "Contents:"
ls -la "$IMG_MNT"/
ls -la "$IMG_MNT"/boot/ 2>/dev/null || true
umount "$IMG_MNT" 2>/dev/null || true
exit 1
fi
echo "==> Found initramfs: $COREGZ"
# Extract initramfs
mkdir -p "$ROOTFS_DIR/rootfs"
cd "$ROOTFS_DIR/rootfs"
zcat "$COREGZ" | cpio -idm 2>/dev/null
# Note: ARM64 kernel comes from build-kernel-arm64.sh, not from piCore
# We only use piCore for the BusyBox userland
cd "$PROJECT_ROOT"
umount "$IMG_MNT" 2>/dev/null || true
rm -rf "$IMG_MNT"
echo "==> ARM64 rootfs extracted: $ROOTFS_DIR/rootfs"
echo " Size: $(du -sh "$ROOTFS_DIR/rootfs" | cut -f1)"
echo "==> Extract complete (ARM64). Kernel will come from build-kernel-arm64.sh"
exit 0
fi
# =========================================================================
# x86_64: Tiny Core ISO extraction
# =========================================================================
TC_ISO="$CACHE_DIR/$TINYCORE_ISO"
ISO_MNT="$ROOTFS_DIR/iso-mount"
if [ ! -f "$TC_ISO" ]; then
echo "ERROR: Tiny Core ISO not found: $TC_ISO"
echo "Run 'make fetch' first."
exit 1
fi
mkdir -p "$ISO_MNT"
# --- Mount ISO and extract kernel + initramfs ---
echo "==> Mounting ISO: $TC_ISO"
mount -o loop,ro "$TC_ISO" "$ISO_MNT" 2>/dev/null || {
# Fallback for non-root: use 7z or bsdtar
echo " mount failed (need root?), trying bsdtar..."
mkdir -p "$ISO_MNT"
bsdtar xf "$TC_ISO" -C "$ISO_MNT" 2>/dev/null || {
echo " bsdtar failed, trying 7z..."
7z x -o"$ISO_MNT" "$TC_ISO" >/dev/null 2>&1
}
}
# Find vmlinuz and core.gz (path varies by Tiny Core version/arch)
VMLINUZ=""
COREGZ=""
for f in "$ISO_MNT"/boot/vmlinuz64 "$ISO_MNT"/boot/vmlinuz; do
[ -f "$f" ] && VMLINUZ="$f" && break
done
for f in "$ISO_MNT"/boot/corepure64.gz "$ISO_MNT"/boot/core.gz; do
[ -f "$f" ] && COREGZ="$f" && break
done
if [ -z "$VMLINUZ" ] || [ -z "$COREGZ" ]; then
echo "ERROR: Could not find vmlinuz/core.gz in ISO"
echo "ISO contents:"
find "$ISO_MNT" -type f
umount "$ISO_MNT" 2>/dev/null || true
exit 1
fi
echo "==> Found kernel: $VMLINUZ"
echo "==> Found initramfs: $COREGZ"
# Copy kernel
cp "$VMLINUZ" "$ROOTFS_DIR/vmlinuz"
# --- Extract initramfs (core.gz → rootfs) ---
echo "==> Extracting initramfs..."
mkdir -p "$ROOTFS_DIR/rootfs"
cd "$ROOTFS_DIR/rootfs"
zcat "$COREGZ" | cpio -idm 2>/dev/null
# Unmount ISO
cd "$PROJECT_ROOT"
umount "$ISO_MNT" 2>/dev/null || true
rm -rf "$ISO_MNT"
echo "==> Rootfs extracted: $ROOTFS_DIR/rootfs"
echo " Size: $(du -sh "$ROOTFS_DIR/rootfs" | cut -f1)"
echo " Kernel: $ROOTFS_DIR/vmlinuz ($(du -h "$ROOTFS_DIR/vmlinuz" | cut -f1))"
# --- Audit kernel config if available ---
if [ -f "$ROOTFS_DIR/rootfs/proc/config.gz" ]; then
echo "==> Kernel config found in rootfs, auditing..."
"$SCRIPT_DIR/../config/kernel-audit.sh" <(zcat "$ROOTFS_DIR/rootfs/proc/config.gz") || true
fi
echo "==> Extract complete."