Defaulting build mode to PIE (and building go in PIE mode)

724 views
Skip to first unread message

timo....@gmail.com

unread,
Apr 28, 2017, 8:33:36 AM4/28/17
to golang-nuts
Hi,

We in Alpine Linux would like to ship Go so that it defaults to PIE buildmode. We acknowledge that Go generally produces safer code, but we still consider it to be viable protection when linking in C (or other) code to Go applications. If the external code has security issues, it is an additional security measure to have main binary PIE built as without that the ASLR is not fully effective. It is also long standing Alpine Linux policy to ship PIE builds if possible.

For Go 1.7 we just used the following patch: https://git.alpinelinux.org/cgit/aports/plain/community/go/default-buildmode-pie.patch and it seems to work.

We are in progress to upgrade to Go 1.8.1, but the same patch no longer works. During the bootstrap build it fails with:
##### Building go_bootstrap for host, linux/amd64.
...
go/parser
go/doc
go/build
cmd/go
2017/04/28 05:52:33 cannot handle R_TLS_IE (sym sync/atomic.(*Value).Store) when linking internally
go tool dist: FAILED: /home/tteras/aports/community/go/src/go/pkg/tool/linux_amd64/link -o /home/tteras/aports/community/go/src/go/pkg/tool/linux_amd64/go_bootstrap /tmp/go-tool-dist-538310359/cmd/go/_go_.a: exit status 1

This seems to be related to using the internal linker. Apparently it is tried regardless of PIE mode. Any suggestions how to fix this (other than the obvious use regular exe build mode)?

I also tried the following patch, but it did not help:

--- go.orig/src/cmd/link/internal/ld/config.go    2017-04-07 16:54:08.000000000 +0000
+++ go/src/cmd/link/internal/ld/config.go    2017-04-27 13:44:30.878077639 +0000
@@ -195,12 +195,8 @@
     case BuildmodeCShared:
         return true, "buildmode=c-shared"
     case BuildmodePIE:
-        switch obj.GOOS + "/" + obj.GOARCH {
-        case "linux/amd64":
-        default:
-            // Internal linking does not support TLS_IE.
-            return true, "buildmode=pie"
-        }
+        // Internal linking does not support TLS_IE.
+        return true, "buildmode=pie"
     case BuildmodePlugin:
         return true, "buildmode=plugin"
     case BuildmodeShared:

I am wondering how the default buildmode could be changed to PIE natively. Perhaps a build time configuration (environment) option for the default build mode could be added?

Thanks,
Timo

Ian Lance Taylor

unread,
Apr 28, 2017, 10:11:19 AM4/28/17
to timo....@gmail.com, golang-nuts
It sounds like you are running into some version of
https://golang.org/issue/18968. But to be honest I don't understand
what is forcing internal link mode. The linker defaults to using
external link mode with PIE. Using -linkmode=internal will override
that, but I don't see where any explicit -linkmode=internal would come
from.

And come to think of it the error seems to be happening at the wrong
time. The go_bootstrap build is built with the existing toolchain,
not the new one. I'm not sure what is happening.


> I also tried the following patch, but it did not help:
>
> --- go.orig/src/cmd/link/internal/ld/config.go 2017-04-07
> 16:54:08.000000000 +0000
> +++ go/src/cmd/link/internal/ld/config.go 2017-04-27 13:44:30.878077639
> +0000
> @@ -195,12 +195,8 @@
> case BuildmodeCShared:
> return true, "buildmode=c-shared"
> case BuildmodePIE:
> - switch obj.GOOS + "/" + obj.GOARCH {
> - case "linux/amd64":
> - default:
> - // Internal linking does not support TLS_IE.
> - return true, "buildmode=pie"
> - }
> + // Internal linking does not support TLS_IE.
> + return true, "buildmode=pie"
> case BuildmodePlugin:
> return true, "buildmode=plugin"
> case BuildmodeShared:

No, I wouldn't expect that to help, because the code that calls
mustLinkExternal already has an override to force external linking
mode for PIE. Something is passing -linkmode=internal but I'm not
sure what.

I assume you are not setting GO_EXTLINK_ENABLED in the environment.


> I am wondering how the default buildmode could be changed to PIE natively.
> Perhaps a build time configuration (environment) option for the default
> build mode could be added?

Yes, perhaps.

Ian

timo....@gmail.com

unread,
May 1, 2017, 8:56:32 AM5/1/17
to golang-nuts, timo....@gmail.com
Hi,

The error message indicates that the internal linker of the new go being built is used.

But as a reference, the bootstrap-go in question is Alpine build of Go 1.7.4 which is patched to default to buildmode=pie. 
 
> I also tried the following patch, but it did not help:
No, I wouldn't expect that to help, because the code that calls
mustLinkExternal already has an override to force external linking
mode for PIE.  Something is passing -linkmode=internal but I'm not
sure what.

I assume you are not setting GO_EXTLINK_ENABLED in the environment.

Correct. GO_EXTLINK_ENABLED is unset. Setting it to '1' (for the bootstrap-go) did not help.

Setting it to '1' for Go 1.8.x results in different errors:

First the following:
##### Building go_bootstrap for host, linux/amd64.
...
cmd/go
runtime (darwin/386)

(it's being built on linux host... but is it misdetecting it as Darwin?)

Later it fails at:
##### Building packages and commands for darwin/386.
...
cmd/vet
# cmd/pack
warning: unable to find runtime/cgo.a
/home/tteras/aports/community/go/src/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/lib/gcc/x86_64-alpine-linux-musl/6.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: unrecognized option '-pagezero_size'
/usr/lib/gcc/x86_64-alpine-linux-musl/6.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status

Seems to be passing darwin options to host's GNU ld.
 
> I am wondering how the default buildmode could be changed to PIE natively.
> Perhaps a build time configuration (environment) option for the default
> build mode could be added?

Yes, perhaps.

That would be lovely. Should I file a github issue about this?

Thanks,
Timo
 

timo....@gmail.com

unread,
May 1, 2017, 9:17:16 AM5/1/17
to golang-nuts, timo....@gmail.com
Ok, the full build is also doing cross-compilers. And seems things go wrong when building the first cross-compiler.

I added GOHOSTARCH, and removed the --no-clean flag from make.bash calls. And now it's progressing further. I wonder how to avoid recompiling the host tools all the time...


Reply all
Reply to author
Forward
0 new messages