Skip to content

nightly.yml: CARGO_TARGET_..._MUSL_LINKER=musl-gcc can silently produce a dynamically-linked binary (re-opens #616 conditions) #683

Description

@logbie

Summary

nightly.yml's build-linux job sets both of these:

CC_x86_64_unknown_linux_musl: musl-gcc
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc   # <- this one

The second is unnecessary, and on a builder image whose musl-gcc specs point at musl's dynamic loader it silently produces a dynamically-linked binary — the exact condition #616 was closed to prevent. It happens to be harmless on blacksmith-8vcpu-ubuntu-2404 today, so this is a latent dependency on the runner image rather than a live breakage. But it means the nightly's static-linkage guarantee rests on a property of the image that nothing pins or asserts.

Evidence

Measured while building wfl from source on rust:1-bookworm (musl-tools 1.2.3, rustc 1.97.1), same env vars as nightly.yml, three configurations:

Configuration Result
musl target, rustc's default linker static-pie
+ CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc dynamic
+ that, plus an explicit -C target-feature=+crt-static`` still dynamic

The produced binary requested /lib/ld-musl-x86_64.so.1. crt-static cannot win the argument back once musl-gcc drives the link: musl-gcc is a spec-file wrapper around the host gcc, and its specs select the dynamic loader. Rust's x86_64-unknown-linux-musl target ships its own self-contained musl libc and static-links by default, so the fix is simply not to take the link away from it.

Why it's worth caring about

This fails quietly at every layer a person would normally check:

  • the build goes green
  • ldd reports statically linked (it is reporting on the wrong thing)
  • file says dynamically linked, interpreter /lib/ld-musl-x86_64.so.1 — which is easy to skim past when you were expecting a musl binary and just saw the word "musl"

The PT_INTERP assertion added in this job is what catches it, and it caught it immediately in my case — that check is doing real work and is worth keeping exactly as it is. But if the builder image ever shifts, the symptom will be a red nightly with a confusing message rather than a clean build, and whoever debugs it will start from "why is our musl build not static" instead of "which of these two env vars is fighting the other".

Suggested fix

Drop the linker line; keep CC_, which is genuinely needed so cc-rs compiles aws-lc-sys for the musl target:

     env:
       TARGET: x86_64-unknown-linux-musl
       CC_x86_64_unknown_linux_musl: musl-gcc
-      CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: musl-gcc
       CARGO_PROFILE_RELEASE_DEBUG: false

Optionally make the intent explicit rather than implicit in the target default:

      CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-C target-feature=+crt-static"

That variable is unioned with the cfg(target_os = "linux") rustflags in .cargo/config.toml, so the 8 MB stack-size link-arg the parser depends on is still applied — I verified GNU_STACK remains 0x800000 with it set.

What I verified, and what I didn't

Verified: with the linker line removed and CC_ kept, a full cargo build --release --locked --target x86_64-unknown-linux-musl of both wfl and wfl-lsp at 150c8a7 (26.7.64) succeeds — aws-lc-sys and the whole graph build fine — and both binaries come out with no PT_INTERP segment. The resulting wfl (22 MB stripped) runs on Ubuntu 22.04 / glibc 2.35 and executes TestPrograms/basic_syntax_comprehensive.wfl, so the #616 property genuinely holds.

Not verified: I did this on rust:1-bookworm, not on blacksmith-8vcpu-ubuntu-2404. I have no reason to expect a difference — removing the override moves the build toward rustc's default behaviour rather than away from it — but I haven't run it on your actual runner.

Happy to send a PR if the change looks right to you.


Filed by the WFL repo warden (automated maintenance pass). Found while building the runtime from source for a downstream project that needs WFL fixes before the nightly carrying them publishes.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions