FS#60928 - [go] [go-pie] the default go installation should be pie-enabled

Attached to Project: Community Packages
Opened by Eli Schwartz (eschwartz) - Wednesday, 28 November 2018, 21:21 GMT
Last edited by Morten Linderud (Foxboron) - Monday, 18 May 2020, 17:45 GMT
Task Type Feature Request
Category Security
Status Closed
Assigned To Bartłomiej Piotrowski (Barthalion)
Morten Linderud (Foxboron)
Architecture All
Severity Medium
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 2
Private No

Details

We try to recommend the use of the go-pie package, but the default go package does not use pie. The only reason we have both, IIRC, is because some packages would not compile with the PIE-enabled one.

This being the case, a preferable setup would be to have:

- a go package which provides/replaces go-pie and builds PIE-enabled executables

- a go-nopie package which provides/conflicts go and builds boring non-PIE executables


Other considerations: The latest versions of go support environment $GOFLAGS, where users (and PKGBUILDs) can define e.g. -buildmode=default to disable PIE.
This task depends upon

Closed by  Morten Linderud (Foxboron)
Monday, 18 May 2020, 17:45 GMT
Reason for closing:  Implemented
Additional comments about closing:  Fixed with go-2:1.14.3-1
Comment by Alexander F. Rødseth (xyproto) - Thursday, 29 November 2018, 09:57 GMT
If the latest version of Go respects GOFLAGS, I like that idea that we could have a good default value for GOFLAGS in /etc/makepkg.conf, and then perhaps only have one single "go" package. But I'm open to any solution.
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 29 November 2018, 12:47 GMT
Yes, one Go package should be enough, and people should override `no-pie` in the failing PKGBUILD. We don’t need to wait for a makepkg update though if that would take too long, we can already merge go-pie into go and tell people to override in their PKGBUILD if required. Then when makepkg is patched, we can revert go(-pie) to the normal go.
Comment by Eli Schwartz (eschwartz) - Thursday, 29 November 2018, 16:05 GMT
Hmm, as mentioned by Barthalion on IRC, enabling PIE on all systems by default if it sometimes does not work, is not quite comparable to gcc.

"ssp/pie enforced by gcc at worst exposes badly written makefiles"

At the same time, we want to enforce this (where it works) on a distribution level, as a default. This is primarily targeted at packaging, which is an environment we can control...

As I understand it, GOFLAGS are read by the go compiler itself, whereas CFLAGS/LDFLAGS are a convention read by Makefiles and passed as arguments *to* gcc... so there's more benefit to sneaking around the environment variable for gcc and badly written Makefiles than there is for golang.

...

This being the case, maybe it does make more sense to add first-class support for GOFLAGS in makepkg itself, then set this as a distribution packaging default. Benefits: Enabling PIE, enabling debug support via OPTIONS=(), possibly configuring optimization levels, etc.

I can put in the work to push this into makepkg.

How this works:

- makepkg.conf will contain $FOO and $FOO_DEBUG settings for a given type of flag

-- $FOO (or GOFLAGS) contains the default flags passed for all packages

-- $FOO_DEBUG (or GOFLAGS_DEBUG) contains additional flags appended as GOFLAGS="$GOFLAGS $GOFLAGS_DEBUG", iff the user has debug packages enabled. The flags are cumulative and can override the default flags, but both will be passed.

- makepkg will handle the process of exporting the $FOO (or GOFLAGS) variable.

-- If options=(!buildflags) is set in the PKGBUILD, all build flags will be unset instead. More fine-grained control can be achieved by the PKGBUILD itself setting: `export GOFLAGS="${GOFLAGS/--bad-flag/}"` to filter out bad flags.

-- If the package is debug-enabled, gcc's CFLAGS will also receive the (not configurable) flag -fdebug-prefix-map=$srcdir=${DBGSRCDIR:-/usr/src/debug} which ensures that debug data references to source code files will point to source code packaged in /usr/src/debug/. This assumes that makepkg's "strip" routine can find the source files referenced via the keywords "DW_AT_name"/"DW_AT_comp_dir" (from readelf --debug-dump). I can find DW_AT_name in a sample golang binary, but it points to e.g. "github.com/keybase/client/go/vendor/github.com/keybase/go-crypto/ssh/terminal.keyCtrlC" which appears to be a ${GOPATH}-relative import path for a symbol contained inside .../ssh/terminal/terminal.go, which is not at all similar. So, how does golang work instead?

...

So the question becomes, what should go inside those variables in order to ensure the best out-of-the-box experience from a distribution packaging perspective?
Comment by Bartłomiej Piotrowski (Barthalion) - Thursday, 29 November 2018, 16:18 GMT
Sorry for not putting my thoughts here yesterday.

As I said on IRC, in my opinion we should ditch go-pie completely, as it's just too simplistic attempt to fix everything, as shown by snapd, containerd or gopass that segfault; instead, just as Eli said, we should make GOFLAGS first class citizen in makepkg.conf and then think about fixing packages that ignore it somehow.

Foxboron said he has figured out what should be in GOFLAGS to make PIE default without breaking projects above.

(Other story is that go-pie is just unsupported upstream as is, which is not what we aim for.)
Comment by Morten Linderud (Foxboron) - Thursday, 29 November 2018, 16:24 GMT
Correction:

I know the GOFLAGS for PIE and relro, along with having a default value for trimpath. I can't make any promises regarding breakage.

For documentation:
export GOFLAGS="-buildmode=pie -gcflags=all=-trimpath=${PWD} -asmflags=all=-trimpath=${PWD} -ldflags=-extldflags=-zrelro -ldflags=-extldflags=-znow"
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 29 November 2018, 16:31 GMT
Shouldn’t we export all our LDFLAGS that way though?
Comment by Morten Linderud (Foxboron) - Thursday, 29 November 2018, 16:49 GMT
Yes. But I'm a bit unsure about the GOFLAGS parser as `-extdlflags=${LDFLAGS}` work if you pass it into `go build` or `go install`. But passing the flags individually trips up things.
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 29 November 2018, 16:51 GMT
Yes I know, I meant something like:
GOFLAGS="-buildmode=pie -gcflags=all=-trimpath=${PWD} -asmflags=all=-trimpath=${PWD} -ldflags=-extldflags=-zrelro -ldflags=-extldflags=-znow -ldflags=-extldflags=-Wl -ldflags=-extldflags=-O1 -ldflags=-extldflags=--sort-common -ldflags=-extldflags=--as-needed"
Comment by Eli Schwartz (eschwartz) - Thursday, 29 November 2018, 17:05 GMT
LDFLAGS are passed to gcc and gcc knows to pass them to /usr/bin/ld because of the -Wl -- so -Wl is not itself an ldflag...
(-Wl,comma,separated,values where "comma" and "separated" and "values" are three flags that /usr/bin/ld will receive.)

@Foxboron, does trimpath do something w.r.t. debugging symbols? If I understand correctly, golang does not recommend using gdb to debug code, but recommends something called "delve" instead. Is there anything we need to do in order to get that to work nicely OOTB, like packaging detached debugging source files for the debugger alongside the detached debugging symbols?
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 29 November 2018, 17:13 GMT
OK, seems we will have a hard time passing the last three then…
Comment by Bruno Pagani (ArchangeGabriel) - Thursday, 29 November 2018, 17:32 GMT
(Just to expand on my previous comment, as explained on IRC you cannot have commas or spaces in the arg of `-ldflags=-extldflags=arg`, even if you quote it)
Comment by Alexander F. Rødseth (xyproto) - Thursday, 06 December 2018, 20:03 GMT
Would it be feasible to patch Go so that we can pass the ldflags we need, either through GOFLAGS or through LDFLAGS? Upstream might even want to accept the patch, if we found a relatively clean solution.

I assume other Linux distros will face the same challenge as well.
Comment by Bartłomiej Piotrowski (Barthalion) - Sunday, 16 December 2018, 21:03 GMT
I tried adding line posted by Morten to containerd's build(), and it did absolutely nothing:

containerd W: ELF file ('usr/bin/containerd-shim') lacks FULL RELRO, check LDFLAGS.
containerd W: ELF file ('usr/bin/containerd-shim-runc-v1') lacks FULL RELRO, check LDFLAGS.
containerd W: ELF file ('usr/bin/containerd-shim') lacks PIE.
containerd W: ELF file ('usr/bin/containerd-shim-runc-v1') lacks PIE.
containerd W: Dependency included and not needed ('runc')

Also test suite fails but I assume that Makefile is doing something stupid:

==> Starting check()...
🇩 test
go test: ldflags flag may be set only once
run "go help test" or "go help testflag" for more information
make: *** [Makefile:150: test] Error 2
Comment by Eli Schwartz (eschwartz) - Sunday, 16 December 2018, 21:14 GMT
I have tried it with "hub".

hub W: ELF file ('usr/bin/hub') lacks FULL RELRO, check LDFLAGS.

But at least no warnings about PIE.
Comment by Bartłomiej Piotrowski (Barthalion) - Sunday, 16 December 2018, 22:30 GMT
As the bottom line is getting rid of go-pie package, GOFLAGS set to -buildmode=pie would be enough for that. From there we could experiment with getting RELRO.
Comment by Jake Kreiger (Magali75) - Wednesday, 19 December 2018, 12:41 GMT
@Barthalion

GO for it!
Comment by Eli Schwartz (eschwartz) - Wednesday, 19 December 2018, 17:29 GMT
Please submit your homonym jokes to a joke website, and don't spam the bugtracker. Thanks.

Loading...