From e5db752c55d320c3cddc663fff65d18376a41af8 Mon Sep 17 00:00:00 2001 From: csh Date: Fri, 22 May 2026 11:58:01 +0800 Subject: [PATCH] :bug: fix(docker_runner): validate act_runner binary arch --- docker-runner/common/setup.sh | 4 ++ docker-runner/common/upgrade.sh | 88 ++++++++++++++++++++++++++++++++- tests/upgrade_test.sh | 76 ++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/docker-runner/common/setup.sh b/docker-runner/common/setup.sh index c96827f..08da6f1 100644 --- a/docker-runner/common/setup.sh +++ b/docker-runner/common/setup.sh @@ -119,6 +119,10 @@ echo "" if curl -L "$DOWNLOAD_URL" -o "$INSTALL_PATH"; then chmod +x "$INSTALL_PATH" + if declare -F validate_binary_arch_or_fail >/dev/null 2>&1; then + validate_binary_arch_or_fail "$INSTALL_PATH" "$RUNNER_ARCH" + fi + # 同时创建软链接到系统路径 ln -sf "$INSTALL_PATH" "$SYSTEM_PATH" diff --git a/docker-runner/common/upgrade.sh b/docker-runner/common/upgrade.sh index 242f5f3..96ac31d 100644 --- a/docker-runner/common/upgrade.sh +++ b/docker-runner/common/upgrade.sh @@ -88,6 +88,73 @@ detect_runner_arch() { esac } +detect_binary_arch_from_file() { + local binary_path=$1 + local magic="" + local low_byte="" + local high_byte="" + local machine_hex="" + + if [ ! -f "${binary_path}" ]; then + echo "unknown" + return 0 + fi + + magic=$(od -An -t x1 -N 4 "${binary_path}" 2>/dev/null | tr -d ' \n') + if [ "${magic}" != "7f454c46" ]; then + echo "unknown" + return 0 + fi + + read -r low_byte high_byte <<<"$(od -An -t x1 -j 18 -N 2 "${binary_path}" 2>/dev/null)" + if [ -z "${low_byte:-}" ] || [ -z "${high_byte:-}" ]; then + echo "unknown" + return 0 + fi + + machine_hex="${high_byte}${low_byte}" + + case "${machine_hex}" in + 003e) + echo "amd64" + ;; + 00b7) + echo "arm64" + ;; + 0028) + echo "arm-7" + ;; + *) + echo "unknown" + ;; + esac +} + +binary_arch_matches_target() { + local binary_path=$1 + local expected_arch=$2 + local detected_arch="" + + detected_arch=$(detect_binary_arch_from_file "${binary_path}") + [ "${detected_arch}" = "${expected_arch}" ] +} + +validate_binary_arch_or_fail() { + local binary_path=$1 + local expected_arch=$2 + local detected_arch="" + + detected_arch=$(detect_binary_arch_from_file "${binary_path}") + + if [ "${detected_arch}" = "unknown" ]; then + fail "Unable to detect downloaded binary architecture: ${binary_path}" + fi + + if [ "${detected_arch}" != "${expected_arch}" ]; then + fail "Downloaded binary architecture mismatch: expected ${expected_arch}, got ${detected_arch}" + fi +} + get_installed_version() { local output="" @@ -102,6 +169,16 @@ get_installed_version() { fi } +get_installed_binary_arch() { + if [ -x "${INSTALL_PATH}" ]; then + detect_binary_arch_from_file "${INSTALL_PATH}" + elif command -v act_runner >/dev/null 2>&1; then + detect_binary_arch_from_file "$(command -v act_runner)" + else + echo "unknown" + fi +} + list_registered_runners() { local runner_dir @@ -154,6 +231,7 @@ download_and_install() { log "Downloading ${url}" curl -fL "${url}" -o "${tmp_path}" chmod +x "${tmp_path}" + validate_binary_arch_or_fail "${tmp_path}" "${arch}" downloaded_version=$("${tmp_path}" --version 2>/dev/null | extract_version_number) if [ "${downloaded_version}" != "${version}" ]; then @@ -205,6 +283,7 @@ main() { local target_arch="" local auto_confirm="false" local current_version="" + local current_arch="unknown" local runner_names=() while [ $# -gt 0 ]; do @@ -252,13 +331,18 @@ main() { target_arch=$(detect_runner_arch) fi - if [ -n "${current_version}" ] && [ "${current_version}" = "${target_version}" ]; then - log "act_runner is already at the latest version: ${current_version}" + current_arch=$(get_installed_binary_arch || true) + + if [ -n "${current_version}" ] && \ + [ "${current_version}" = "${target_version}" ] && \ + [ "${current_arch}" = "${target_arch}" ]; then + log "act_runner is already at the requested version and architecture: ${current_version} (${current_arch})" exit 0 fi log "Upgrade summary:" log " Current version: ${current_version:-not installed}" + log " Current arch: ${current_arch:-unknown}" log " Target version: ${target_version}" log " Architecture: ${target_arch}" log " Install path: ${INSTALL_PATH}" diff --git a/tests/upgrade_test.sh b/tests/upgrade_test.sh index 5f1fd01..1b08d61 100644 --- a/tests/upgrade_test.sh +++ b/tests/upgrade_test.sh @@ -20,6 +20,31 @@ assert_eq() { fi } +make_fake_elf() { + local path=$1 + local arch=$2 + local machine_bytes="" + + case "${arch}" in + amd64) + machine_bytes='\076\000' + ;; + arm64) + machine_bytes='\267\000' + ;; + arm-7) + machine_bytes='\050\000' + ;; + *) + echo "FAIL: unsupported fake ELF arch ${arch}" >&2 + exit 1 + ;; + esac + + printf '\177ELF\002\001\001\000\000\000\000\000\000\000\000\000\002\000%b' \ + "${machine_bytes}" > "${path}" +} + test_extract_versions_from_listing() { local html html=$(cat <<'EOF' @@ -90,10 +115,61 @@ test_resolve_latest_version_or_fallback_uses_fallback() { "resolve_latest_version_or_fallback should fall back when detected version is invalid" } +test_detect_binary_arch_from_file() { + local temp_root amd64_file arm64_file arm7_file text_file + + temp_root=$(mktemp -d) + amd64_file="${temp_root}/act_runner-amd64" + arm64_file="${temp_root}/act_runner-arm64" + arm7_file="${temp_root}/act_runner-arm7" + text_file="${temp_root}/not-elf" + + make_fake_elf "${amd64_file}" "amd64" + make_fake_elf "${arm64_file}" "arm64" + make_fake_elf "${arm7_file}" "arm-7" + printf 'not an elf\n' > "${text_file}" + + assert_eq "amd64" "$(detect_binary_arch_from_file "${amd64_file}")" \ + "detect_binary_arch_from_file should recognize amd64 ELF binaries" + assert_eq "arm64" "$(detect_binary_arch_from_file "${arm64_file}")" \ + "detect_binary_arch_from_file should recognize arm64 ELF binaries" + assert_eq "arm-7" "$(detect_binary_arch_from_file "${arm7_file}")" \ + "detect_binary_arch_from_file should recognize arm-7 ELF binaries" + assert_eq "unknown" "$(detect_binary_arch_from_file "${text_file}")" \ + "detect_binary_arch_from_file should reject non-ELF files" + + rm -rf "${temp_root}" +} + +test_binary_arch_matches_target() { + local temp_root amd64_file arm64_file + + temp_root=$(mktemp -d) + amd64_file="${temp_root}/act_runner-amd64" + arm64_file="${temp_root}/act_runner-arm64" + + make_fake_elf "${amd64_file}" "amd64" + make_fake_elf "${arm64_file}" "arm64" + + if ! binary_arch_matches_target "${amd64_file}" "amd64"; then + echo "FAIL: binary_arch_matches_target should accept matching architectures" >&2 + exit 1 + fi + + if binary_arch_matches_target "${arm64_file}" "amd64"; then + echo "FAIL: binary_arch_matches_target should reject mismatched architectures" >&2 + exit 1 + fi + + rm -rf "${temp_root}" +} + test_extract_versions_from_listing test_pick_latest_version test_extract_version_number_accepts_v_prefix test_resolve_latest_version_or_fallback_prefers_latest test_resolve_latest_version_or_fallback_uses_fallback +test_detect_binary_arch_from_file +test_binary_arch_matches_target echo "upgrade_test.sh: PASS"