Repository navigation
Add a static-PIE entry point and converter for Linux tsc - #65122
Draft
Jake Bailey (jakebailey) wants to merge 3 commits into
Draft
Jake Bailey (jakebailey) wants to merge 3 commits into
Jake Bailey (jakebailey) wants to merge 3 commits into
Conversation
We are required to ship position-independent executables. Go's internal linker can build a PIE without cgo on several Linux architectures, but the result names the glibc dynamic loader as its interpreter, so it no longer starts on musl systems like Alpine, in distroless images, or on NixOS, all of which run today's static binaries fine. Go-linked PIEs only need R_*_RELATIVE relocations and set up their own TLS, so the loader has very little to do. Link a small entry point into tsc that does that work itself, and add a tool that removes PT_INTERP and points the ELF entry at it, producing a static-PIE that runs on any Linux system.
On linux amd64, arm64, loong64, ppc64le, and s390x, Go can link a PIE without an external linker, so build those as PIE with BIND_NOW and convert them to static-PIE to keep them portable across libcs. Other Linux targets would need an external linker for PIE and stay as they are; Windows, macOS, and Android binaries are already PIE.
The converter rejected a fixed list of things it knew needed a dynamic loader, so anything new that a future Go linker emits for the loader to act on (a hardening property note, a new relocation format) would have been silently dropped along with PT_INTERP. Accept only the program headers, dynamic tags, and flag bits that Go emits today and that the entry point fully handles, so such a change fails the build instead.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is absolutely diabolical and I don't think I want to merge this, but one reason we can't really do
-buildmode=pieis because we don't want to depend on libc, whose dynamic loader is literally hardcoded in the binary (boo).But, I of course asked copilot "can we somehow patch a Go produced binary to make it PIE" and it came up with this idea, to build with
-buildmode=pie, then patch the output to make it not use the hardcoded one but a function inside the binary itself, as Go doesn't actually use any complicated relocations.This is exactly what
gcc -static-pieor glibc--enable-static-pieormusldo.I'm wondering if this is something that could be upstreamed, because it's quite interesting. But I'm opening the PR just to have it anyway.