Skip to content

Exec format error when execution platform differs from host platform #8

Open

Description

@trevorc

Issue description

When using rules_kustomize in an environment where the Bazel host platform is incompatible with the execution platform, rules_kustomize will fetch the wrong toolchain. I noticed this when running rules_kustomize on a remote executor with a mismatched CPU architecture from my host.

The underlying issue is that the toolchains do not distinguish between the host platform (i.e., where Bazel runs) and the execution platform.

Currently, the repository rules for kustomize and helm detect the OS and architecture of the host machine and download a single binary matching that host. However, the toolchain registration logic declares toolchains for all supported platforms, and points every single one of them to this same host-architecture binary. When Bazel's toolchain resolution selects the toolchain for a remote execution platform, it is provided with the host's binary. The executor then attempts to run an incompatible binary, leading to a failure (in this case, "Exec format error").

How to reproduce the issue

You can observe this behavior locally by defining a platform and using aquery to trigger the analysis phase so we can observe the architecture of the toolchain that gets downloaded.

  1. Prepare your workspace with a kustomization.yaml file, and add the following to your BUILD file (assuming your host machine is x86_64):
load("@rules_kustomize//kustomize:kustomize.bzl", "kustomization", "kustomized_resources")
  
platform(
    name = "linux_arm64",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:aarch64",
    ],
)

kustomization(
    name = "overlay",
    srcs = ["kustomization.yaml"],
)

kustomized_resources(
    name = "manifests",
    kustomization = ":overlay",
)
  1. Run an action query, overriding the execution platform to the one you just defined:
    bazel aquery 'mnemonic("KustomizeBuild", //:manifests)' --extra_execution_platforms=//:linux_arm64
    If you inspect the output's Inputs: array, you'll see the binary Bazel selected for this arm64 action is:
    external/rules_kustomize++kustomize+kustomize_tool/kustomize
  2. To prove this binary is for the wrong architecture, inspect it using the file command inside Bazel's output base:
$ file $(bazel info output_base)/external/rules_kustomize++kustomize+kustomize_tool/kustomize
.../kustomize: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

By parameterizing the toolchain in the execution platform, like in PR #7, after running the aquery command above, you would instead see in the Inputs: section of aquery's output a path which reflects the execution platform:

    Inputs: [..., external/rules_kustomize++kustomize+kustomize_tool_linux_arm64/kustomize, ...]

Finally, to prove that toolchain resolution correctly provided an arm64 binary, run the file command on that new path:

$ file $(bazel info output_base)/external/rules_kustomize++kustomize+kustomize_tool_linux_arm64/kustomize
 .../kustomize: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions