-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/go: Can't override linkmode when setting buildmode=pie #44480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
How do you conclude that external linking is not used? I think the fact that it printed |
If the program doesn't use cgo but you want to pass flags to external linker, you can pass |
λ fzf » export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -ldflags=-v" λ fzf » CGO_ENABLED=0 go build -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 96932 symbols, 27963 reachable 1 package symbols, 36428 hashed symbols, 54613 non-package symbols, 5890 external symbols 135636 liveness data λ fzf » CGO_ENABLED=1 go build -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 96932 symbols, 27963 reachable 1 package symbols, 36428 hashed symbols, 54613 non-package symbols, 5890 external symbols 135636 liveness data
|
Okay, messing up the GOFLAGS env variable (It seems like it doesn't like having multiple -ldflags...) This is with patch 6c0135d reverted λ fzf » export GOFLAGS="-buildmode=pie -trimpath" λ fzf » CGO_ENABLED=0 /home/fox/Git/prosjekter/Go/go/bin/go build -ldflags '-linkmode=external -v' -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 loadinternal: cannot find runtime/cgo host link: "gcc" "-m64" "-Wl,-z,relro" "-pie" "-o" "/tmp/go-build3834599149/b001/exe/a.out" "-rdynamic" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-286472386/go.o" 96924 symbols, 40660 reachable 1 package symbols, 36428 hashed symbols, 54613 non-package symbols, 5882 external symbols 135636 liveness data λ fzf » CGO_ENABLED=1 /home/fox/Git/prosjekter/Go/go/bin/go build -ldflags '-linkmode=external -v' -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 host link: "gcc" "-m64" "-Wl,-z,relro" "-pie" "-o" "/tmp/go-build1452289956/b001/exe/a.out" "-rdynamic" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-964871768/go.o" "/tmp/go-link-964871768/000000.o" "/tmp/go-link-964871768/000001.o" "/tmp/go-link-964871768/000002.o" "/tmp/go-link-964871768/000003.o" "/tmp/go-link-964871768/000004.o" "/tmp/go-link-964871768/000005.o" "/tmp/go-link-964871768/000006.o" "/tmp/go-link-964871768/000007.o" "/tmp/go-link-964871768/000008.o" "/tmp/go-link-964871768/000009.o" "/tmp/go-link-964871768/000010.o" "/tmp/go-link-964871768/000011.o" "/tmp/go-link-964871768/000012.o" "-g" "-O2" "-lpthread" 97087 symbols, 40831 reachable 1 package symbols, 36438 hashed symbols, 54654 non-package symbols, 5994 external symbols 135848 liveness data This is with 1.16 λ fzf » export GOFLAGS="-buildmode=pie -trimpath" λ fzf » CGO_ENABLED=1 go build -ldflags '-linkmode=external -v' -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 loadinternal: cannot find runtime/cgo host link: "gcc" "-m64" "-Wl,-z,relro" "-pie" "-o" "/tmp/go-build3793652355/b001/exe/a.out" "-rdynamic" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-943503868/go.o" 96924 symbols, 40660 reachable 1 package symbols, 36428 hashed symbols, 54613 non-package symbols, 5882 external symbols 135636 liveness data λ fzf » CGO_ENABLED=0 go build -ldflags '-linkmode=external -v' -o fzf # github.com/junegunn/fzf HEADER = -H5 -T0x401000 -R0x1000 loadinternal: cannot find runtime/cgo host link: "gcc" "-m64" "-Wl,-z,relro" "-pie" "-o" "/tmp/go-build3793652355/b001/exe/a.out" "-rdynamic" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-943503868/go.o" 96924 symbols, 40660 reachable 1 package symbols, 36428 hashed symbols, 54613 non-package symbols, 5882 external symbols 135636 liveness data |
As you posted, For the runtime/cgo package, #31544 is related. cmd/go has logic to include runtime/cgo if external linking is requested, but somehow that logic doesn't work (unrelated to the change you reverted). |
Should we rename this bugreport to be about the patch altering the |
It is "related" in that PIE used to always include runtime/cgo, and that change stops doing that. That is intentional, and I don't think we want to revert that. Now it's up to -linkmode=external to include runtime/cgo, but that somehow doesn't always work. Why would you want to force the inclusion of runtime/cgo?
I think we can combine it to #31544 and close this. |
Right, I get the issue now. However I think the patch should be reverted since this is quite a severe regression for binary hardening for distributions and introduces faulty/buggy behavior. What would be the downside of reverting the patch? |
You haven't explain why you'd want to force the inclusion of runtime/cgo. Thanks. |
Have you tried |
I thought it was clear. Sorry. This solves binary hardening for Arch Linux as passing go build -ldflags '-linkmode=external -extldflags=-Wl,-z,relro,-z,now' -o fzf This works but passing the equivalent through |
Thanks for the reply. So
PIE implying cgo is never the intention. Forcing the inclusion of C has never been supported (feel free to raise a feature request if you need it). Thanks. |
It still leaves out a lot to be desired though. You can't realistically pass |
@mvdan Ah yes. That is the crux of the flag issues. But then I'll close this issue and contemplate reverting the commit downstream in Arch. It's annoying that intended and unintended usage of these flags is never defined and just breaks between releases without any notes in the release notes. |
Sorry for the breakage. The intended use of So I think the intended use of these flags is defined. I agree that unintended use of these flags can change between releases, and I agree that that is unfortunate. But it was documented in the release notes: https://golang.org/doc/go1.15#linker. |
If you read over the command output you see λ fzf » export CGO_LDFLAGS="-Wl,-z,relro,-z,now" λ fzf » export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external" # We ask go to enable CGO. No dice. Documented bug λ fzf » CGO_ENABLED=1 go build -buildmode=pie -o fzf # github.com/junegunn/fzf loadinternal: cannot find runtime/cgo λ fzf » checksec --file=./fzf RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 4594) Symbols No 0 0 ./fzf ^^^^^^^^^^^^^ # Works. It uses CGO_LDFLAGS λ fzf » CGO_ENABLED=1 go build -buildmode=pie -o fzf main.go λ fzf » checksec --file=./fzf RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 4692) Symbols Yes 2 2 ./fzf ^^^^^^^^^^ |
So the issue is that we now have to pass |
I'm not completely sure what you are saying, but I want to clarify that setting Using |
But you can't pass those flags through the For Linux distributions this is all extremely limiting. I have spent many hours patching
The original issue was misguided as the compiler is complicated, but the situation is extremely confusing when you try do something that isn't straight forward with the compiler and compile flags 😞 Apologies for the noise |
I figured out that The issue is that #15485 failed to mention I'll figure out a patch for that and see what happens. |
It sounds like you are saying that |
Using |
Yes
This should give you a noisy overview how https://github.com/search?q=go+build+GOFLAGS&type=Code An example from a popular upstream: https://github.com/helm/helm/blob/6092f01fac0770009cd2cdad9541dd475c254d38/Makefile#L17 I found autoconf uses the flag for command-line arguments from 2010. I know this is only for gccgo, and I did spot the author. But it might have given some influence for using GOFLAGS for compiler flags in existing build systems before go upstream adopted it. https://git.savannah.gnu.org/cgit/autoconf.git/tree/lib/autoconf/go.m4#n33 Changing this everywhere breaks existing build systems since the I think we are way off what the original issue was about. I'm not sure if you want a new issue for this?
I'll submit a patch proposal so we can work something out. But I don't see why you wouldn't want full relro. The original commit didn't really mention why relro was added in the first place. |
Yes, we should probably have two new issues: one for (From my perspective, |
Ack. Thanks for listening and I'll try hack on the linker! |
Most Linux distributions today enable PIE and full RELRO on all binaries to make exploitation harder. When buildmode=pie is used we enable full relro as that is probably what most people want regardless. This introduces a negligible startup time for binaries. https://fedoraproject.org/wiki/Changes/Harden_All_Packages https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro Related golang#44480 Signed-off-by: Morten Linderud <morten@linderud.pw>
Most Linux distributions today enable PIE and full RELRO on all binaries to make exploitation harder. When buildmode=pie is used we enable full relro as that is probably what most people want regardless. This introduces a negligible startup time for binaries. https://fedoraproject.org/wiki/Changes/Harden_All_Packages https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro Related golang#44480
Change https://golang.org/cl/312509 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
The commit 6c0135d breaks RELRO as there is no way to override which linker to use when
-buildmode=pie
is set and the target islinux/amd64
. This makes it impossible to build hardened binaries on most Linux platforms.I'm not sure if it's intentional to force the internal linker? Shoulnd't
-linkmode=external
ensure we don't use the internal linker?https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: