-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
cmd/go: default buildmode incompatible to external linker with PIE enabled by default #17847
Comments
The issue is discussed at: https://groups.google.com/forum/#!topic/golang-dev/gRCe5URKewI |
Looking further into this, I realize that there are still things I don't understand. By default, the go tool is not built in external linking mode. Why is that happening for you? When I run By default, Go code is compiled such that it can be successfully linked into a PIE. Why is that not happening for you? When I run Why do your go tool crash? Can you run it under gdb and see where it goes wrong? |
Something that's not made obvious enough in the report is that this is on aarch64 on alpine, so with musl as libc. But even so I don't know why this wouldn't work, Ian's points are still very relevant. |
There are three preconditions to reproduce the crash
I have used GDB to analyze the crash and find that it's due to following abnormal ELF relocation items:
......
So the crash occurs when musl ld is trying to fill relocation address to these items at runtime Alpine community also has a workaround for the crash, as can be seen here: http://git.alpinelinux.org/cgit/aports/tree/community/go/default-buildmode-pie.patch It's interesting that X86_64 linker seems to be able to handle the "PIE" linking for "exe" buildmode. But l'd say Go needs to explicitly disable "PIE" for "exe" buildmode instead of relying on the default behavior of external linker. So i suggest fixing the issue by turning PIE off explicitly via "-no-pie" (if recognized by GCC) when invoking external linker for "exe" buildmode. |
A similar thing happens on amd64--there are Can you run Do you know if there is something on your system that disables |
Sounds like a good idea to me, I think (this stuff is fairly confusing!). Does the new linkmode=internal buildmode=pie do the relro stuff? |
Yes, |
CL https://golang.org/cl/33014 mentions this issue. |
The relro idea doesn't work, because on some platforms you have to compile with I'd still like to understand exactly what is going wrong on Alpine GNU/Linux. |
On 10 November 2016 at 11:27, Ian Lance Taylor notifications@github.com
I googled about a bit and it seems that perhaps PIE executables with (BTW, because I'd forgotten this temporarily, the reason this shows up more |
Well, but |
I think it's more that mprotect(PROT_WRITE|PROT_EXEC) is ignored or On 10 November 2016 at 12:20, Ian Lance Taylor notifications@github.com
|
The dynamic linker doesn't do that for |
Ah, but musl's does not do that: https://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c#n699 (perhaps someone should tell them?) |
|
@mwhudson @ianlancetaylor GoLang has provided a special GOOS option for Android platform to switch from "exe" to "pie". Is the switch for avoiding the similar situation as Alpine of unsupporting TEXTREL? Btw, some platforms may forbid TEXTREL on purpose since it is wasting memory and prevents security hardening. |
I don't understand what you mean by "the code segment has no chance to execute." Can you confirm that Alpine GNU/Linux rejects an If that is so, then it seems that the core problem here is that the musl dynamic linker has a bug in its implementation of Setting In any case, does https://golang.org/cl/33106 work around the problem enough to let Go programs run? |
CL https://golang.org/cl/33106 mentions this issue. |
"go" is firstly loaded by Alpine kernel with "R E" attribute to its code segment and then execution flow is passed to musl linker. There is no mprotect call trying to set both PROT_EXEC and PRO_WRITE inside musl linker before doing relocation. We are trying to contact Alpine guys to understand what's the reason of unsupporting DT_TEXTREL (a bug or a designed feature) Anyway, your cl (https://golang.org/cl/33106) works around the problem and Go programs run in my environment (Alpine ARM64) now |
For two reasons: 1) Alpine has fixed the issue (http://git.alpinelinux.org/cgit/aports/tree/community/go/default-buildmode-pie.patch) 2) The patch doesn't work for some platforms where Golang adopts external linker (golang/go#17847). Although Golang developers has fixed the issue with disabling PIE, above Alpine solution is more secure So, Alpine Go (installed by apk) is better choice.
For two reasons: 1) Alpine has fixed the issue (http://git.alpinelinux.org/cgit/aports/tree/community/go/default-buildmode-pie.patch) 2) The patch doesn't work for some platforms where Golang adopts external linker (golang/go#17847). Although Golang developers has fixed the issue with disabling PIE, above Alpine solution is more secure So, Alpine Go (installed by apk) is better choice.
cc @ncopa |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go version go1.7.3 linux/arm64
What operating system and processor architecture are you using (
go env
)?GOARCH="arm64"
GOBIN=""
GOEXE=""
GOHOSTARCH="arm64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/root/go-go1.7.3"
GOTOOLDIR="/root/go-go1.7.3/pkg/tool/linux_arm64"
CC="gcc"
GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build719384124=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
What did you do?
Following 3 steps
Need a GCC with PIE enabled by default
e.g.,
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/aarch64-alpine-linux-musl/6.2.1/lto-wrapper
Target: aarch64-alpine-linux-musl
Configured with: /home/buildozer/aports/main/gcc/src/gcc-6.2.0/configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --build=aarch64-alpine-linux-musl --host=aarch64-alpine-linux-musl --target=aarch64-alpine-linux-musl --with-pkgversion='Alpine 6.2.1' --enable-checking=release --disable-fixed-point --disable-libstdcxx-pch --disable-multilib --disable-nls --disable-werror --disable-symvers --enable-__cxa_atexit --enable-default-pie --enable-cloog-backend --enable-languages=c,c++,objc,java,fortran,ada --with-arch=armv8-a --with-abi=lp64 --disable-bootstrap --disable-libquadmath --disable-libssp --disable-libmpx --disable-libmudflap --disable-libsanitizer --enable-shared --enable-threads --enable-tls --with-system-zlib --with-linker-hash-style=gnu
Thread model: posix
gcc version 6.2.1 20160822 (Alpine 6.2.1)
Build Go from source code (./make.bash)
run go command (./go)
What did you expect to see?
run successfully
What did you see instead?
Segmentation fault
The text was updated successfully, but these errors were encountered: