diff --git a/.cargo/config.toml b/.cargo/config.toml index 830d89d1..5ef44537 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,7 @@ [target.aarch64-unknown-linux-musl] -rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-Wl,-z,stack-size=2097152"] +linker = "aarch64-linux-musl-gcc" +rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-static", "-C", "link-arg=-Wl,-z,stack-size=2097152"] [target.x86_64-unknown-linux-musl] -rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-Wl,-z,stack-size=2097152"] +linker = "x86_64-linux-musl-gcc" +rustflags = ["-C", "target-feature=+crt-static", "-C", "link-arg=-static", "-C", "link-arg=-Wl,-z,stack-size=2097152"] diff --git a/scripts/build/build-guest.sh b/scripts/build/build-guest.sh index c4335952..14b0185b 100755 --- a/scripts/build/build-guest.sh +++ b/scripts/build/build-guest.sh @@ -120,26 +120,28 @@ build_guest_binary() { cargo build $build_flag --target "$GUEST_TARGET" -p boxlite-guest - # Verify guest binary is statically linked + # Verify guest binary is truly statically linked (ET_EXEC, not static-PIE). + # Static-PIE (ET_DYN) binaries fail inside the VM because libkrunfw's kernel + # has CONFIG_RANDOMIZE_BASE disabled — the ELF loader can't handle ET_DYN + # without ASLR, causing the guest to exit immediately with no output. local guest_binary="$PROJECT_ROOT/target/$GUEST_TARGET/$PROFILE/boxlite-guest" local file_output file_output=$(file "$guest_binary") - if echo "$file_output" | grep -q "dynamically linked"; then + if ! echo "$file_output" | grep -q "statically linked"; then local musl_arch musl_arch=$(echo "$GUEST_TARGET" | cut -d'-' -f1) local musl_gcc="${musl_arch}-linux-musl-gcc" - print_error "boxlite-guest is dynamically linked, but must be statically linked" + print_error "boxlite-guest is not statically linked" echo "" - echo "❌ Error: The boxlite-guest binary must be statically linked." + echo "❌ Error: The boxlite-guest binary must be truly statically linked (ET_EXEC)." + echo " Static-PIE (ET_DYN) binaries will NOT work inside the VM." echo "" - echo "The guest binary at $guest_binary is dynamically linked, which means" - echo "it depends on shared libraries that won't be available inside the VM." + echo " file output: $file_output" echo "" echo "🔧 To fix this issue:" - echo " Check your $musl_gcc version:" - echo " $ $musl_gcc --version" - echo " Verify whether your C compiler is a gnu-gcc wrapper instead of true musl-gcc" + echo " Ensure .cargo/config.toml has '-C link-arg=-static' in rustflags" + echo " for the $GUEST_TARGET target, and that $musl_gcc is a true musl linker." echo "" exit 1 fi diff --git a/scripts/build/build-runtime.sh b/scripts/build/build-runtime.sh index 50b058e8..2ca139eb 100755 --- a/scripts/build/build-runtime.sh +++ b/scripts/build/build-runtime.sh @@ -311,6 +311,36 @@ assemble_runtime() { echo "✓" fi + # Final gate: verify binaries are truly statically linked before packaging. + # This catches issues regardless of how binaries were built or cached. + if [ "$OS" = "linux" ]; then + echo "" + print_section "Verifying static linking..." + local failed=false + for bin in boxlite-guest boxlite-shim; do + local bin_path="$DEST_DIR/$bin" + if [ -f "$bin_path" ]; then + local file_output + file_output=$(file "$bin_path") + if echo "$file_output" | grep -q "statically linked"; then + print_step "$bin: " + print_success "statically linked ✓" + else + print_error "$bin is NOT statically linked" + echo " file: $file_output" + failed=true + fi + fi + done + if [ "$failed" = true ]; then + echo "" + print_error "Runtime contains non-static binaries. Aborting." + echo " Static-PIE (ET_DYN) binaries will fail inside the VM." + echo " Ensure .cargo/config.toml has '-C link-arg=-static' in rustflags." + exit 1 + fi + fi + print_success "Runtime directory assembled" } diff --git a/scripts/build/build-shim.sh b/scripts/build/build-shim.sh index f2af48f6..ccd23048 100755 --- a/scripts/build/build-shim.sh +++ b/scripts/build/build-shim.sh @@ -105,6 +105,20 @@ build_shim_binary() { else cargo build $build_flag --bin boxlite-shim $features fi + + # Verify shim binary is statically linked on Linux + if [ "$OS" = "linux" ]; then + local file_output + file_output=$(file "$SHIM_BINARY_PATH") + if ! echo "$file_output" | grep -q "statically linked"; then + print_error "boxlite-shim is not statically linked" + echo "" + echo "❌ Error: The boxlite-shim binary must be statically linked." + echo " file output: $file_output" + echo "" + exit 1 + fi + fi } # Sign the binary (macOS only, automatic) diff --git a/scripts/setup/setup-manylinux.sh b/scripts/setup/setup-manylinux.sh index 360066d6..afb8b69d 100755 --- a/scripts/setup/setup-manylinux.sh +++ b/scripts/setup/setup-manylinux.sh @@ -26,6 +26,13 @@ check_platform() { fi } +# Check if we need $SUDO (not root and sudo exists) +if [ "$EUID" -ne 0 ] && command -v sudo &> /dev/null; then + SUDO="sudo" +else + SUDO="" +fi + # Check if a yum package is installed yum_installed() { yum list installed "$1" &>/dev/null @@ -34,7 +41,7 @@ yum_installed() { # Update package lists update_yum() { print_section "🔄 Updating package lists..." - yum update -y -q + $SUDO yum update -y -q echo "" } @@ -52,6 +59,7 @@ install_system_deps() { unzip file # file type detection pkgconfig + patchelf # ELF binary patching (SONAME fixup, wheel repair) openssl-devel # libkrun build dependencies @@ -60,8 +68,7 @@ install_system_deps() { llvm llvm-devel libatomic - libepoxy-devel # Required by rutabaga_gfx for OpenGL - virglrenderer-devel # Required by rutabaga_gfx for GPU virtualization + libepoxy-devel # Required by rutabaga_gfx for OpenGL (optional on headless) # libkrunfw kernel build dependencies bc @@ -90,9 +97,31 @@ install_system_deps() { if yum_installed "$pkg"; then print_success "Already installed" else - echo -e "${YELLOW}Installing...${NC}" - yum install -y -q "$pkg" + # Some packages have -minimal variants (e.g., curl-minimal on Amazon Linux) + # that provide the same command. Skip if the command already exists. + local cmd_name="${pkg%%-*}" # e.g., "curl" from "curl", "gcc" from "gcc-c++" + if [ "$pkg" = "$cmd_name" ] && command -v "$cmd_name" &>/dev/null; then + print_success "Provided by alternative package" + else + echo -e "${YELLOW}Installing...${NC}" + $SUDO yum install -y -q "$pkg" + print_success "$pkg installed" + fi + fi + done + + # Optional GPU packages (not available on all distros, e.g., Amazon Linux 2023) + local optional_packages=( + virglrenderer-devel # Required by rutabaga_gfx for GPU virtualization + ) + for pkg in "${optional_packages[@]}"; do + print_step "Checking for $pkg (optional)... " + if yum_installed "$pkg"; then + print_success "Already installed" + elif $SUDO yum install -y -q "$pkg" 2>/dev/null; then print_success "$pkg installed" + else + echo -e "${YELLOW}Not available (GPU features disabled)${NC}" fi done @@ -103,7 +132,7 @@ install_system_deps() { print_success "Already installed" else echo -e "${YELLOW}Installing...${NC}" - yum install -y -q glibc-static + $SUDO yum install -y -q glibc-static print_success "glibc-static installed" fi @@ -176,7 +205,7 @@ install_protoc() { local PROTOC_ZIP="/tmp/protoc.zip" curl -sSL "$PROTOC_URL" -o "$PROTOC_ZIP" - unzip -q -o "$PROTOC_ZIP" -d /usr/local + $SUDO unzip -q -o "$PROTOC_ZIP" -d /usr/local rm -f "$PROTOC_ZIP" print_success "Installed protoc $PROTOC_VERSION" @@ -216,7 +245,7 @@ install_nodejs() { echo -e "${YELLOW}Downloading Node.js $NODE_VERSION...${NC}" curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" \ - | tar -xJ -C /usr/local --strip-components=1 + | $SUDO tar -xJ -C /usr/local --strip-components=1 print_success "Node.js $NODE_VERSION installed" echo "" } diff --git a/scripts/setup/setup-musllinux.sh b/scripts/setup/setup-musllinux.sh index 6bedf5cf..2d772f57 100755 --- a/scripts/setup/setup-musllinux.sh +++ b/scripts/setup/setup-musllinux.sh @@ -52,6 +52,7 @@ install_system_deps() { unzip file # file type detection pkgconfig + patchelf # ELF binary patching (SONAME fixup, wheel repair) openssl-dev # musl development