runc icon indicating copy to clipboard operation
runc copied to clipboard

`go build -trimpath` makes other arguments ignored in `debug.BuildInfo`

Open deitch opened this issue 2 years ago • 5 comments

Description

go build -trimpath makes the -X ldflags disappear.

The runc build command from the Makefile looks like this:

GO_BUILD := $(GO) build -trimpath $(GO_BUILDMODE) \
	$(EXTRA_FLAGS) -tags "$(BUILDTAGS)" \
	-ldflags "$(LDFLAGS_COMMON) $(EXTRA_LDFLAGS)"

where LDFLAGS_COMMON is set here:

LDFLAGS_COMMON := -X main.gitCommit=$(COMMIT) -X main.version=$(VERSION)

While the provided information is really useful for running runc version, e.g.:

$./runc --version
runc version 1.1.0
commit: v1.1.0-0-g067aaf85
spec: 1.0.2-dev
go: go1.19.4
libseccomp: 2.5.4

(and I particular appreciate the go pseudo-version-compatible commit)

if you run with -trimpath, that information is not saved in debug.BuildInfo, making it harder to use standard tooling to extract it.

Here it is built without -trimpath:

$ go version -m runc
runc: go1.19.4
        path    github.com/opencontainers/runc
        build   -compiler=gc
        build   -ldflags="-X main.gitCommit=v1.1.0-578-g5cf9bb22 -X main.version=1.1.0+dev -linkmode external -extldflags -static-pie "
        build   -tags=seccomp,urfave_cli_no_docs,netgo,osusergo
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=amd64
        build   GOOS=linux
        build   GOAMD64=v1

And the default with -trimpath:

runc: go1.19.4
        path    github.com/opencontainers/runc
        build   -compiler=gc
        build   -tags=seccomp,urfave_cli_no_docs,netgo,osusergo
        build   -trimpath=true
        build   CGO_ENABLED=1
        build   GOARCH=amd64
        build   GOOS=linux
        build   GOAMD64=v1

I think this would be good enough if -trimpath were optional, so builders can choose to select it or not.

Steps to reproduce the issue

  1. Run make -n static to get the build command
  2. Run the provided build command
  3. go version -m runc
  4. Run the same build command, removing -trimpath
  5. go version -m runc

Describe the results you received and expected

Expected debug.BuildInfo to include -X flags and other ldflags and build-time info.

It was missing.

What version of runc are you using?

Latest main HEAD as of today (commit 5cf9bb229feed19a767cbfdf9702f6487341e29e from Wed 14 June 2023). Tried much earlier versions, and with different versions of go as well. Same outcome.

Host OS information

NA

Host kernel information

NA

deitch avatar Jun 16 '23 10:06 deitch

AFAIK there is no standard tooling to get the version information from the way we set versions in the resulting binary. Yes, the -ldflags "-X ..." thing is a common technique but the way this is done varies so much between projects that I'm not sure there are "standard" tools for getting this information programmatically. We officially only really support getting the version from actually running runc version (or runc features, which is explicitly defined by the OCI spec).

All of that being said, I don't mind making it something you can opt-out of but it should be made clear it's needed for reproducible builds. I thought we added -trimpath for reproducibility reasons (which it does help with, though we're missing -buildvcs=false which is needed in the most recent Go versions) but it was added in #2773 with somewhat limited reasoning. In any case, it is needed for reproducible builds in some cases.

cyphar avatar Jun 20 '23 12:06 cyphar

Yeah, this is a longstanding issue of much debate at go. go install off of the net will use the version/pseudo-version and put it in debug.BuildInfo, go build will not, and will not let you override it. Because of that, lots of tools do read -X, like you said.

In any case, if you don't mind it being optional, I can open a PR for it that allows you to override it.

deitch avatar Jun 20 '23 13:06 deitch

See #3908

deitch avatar Jun 20 '23 13:06 deitch

Yeah, I find it quite strange that -trimpath does more than it says on the tin -- it seems to me that ldflags is something that really shouldn't be stripped when you're just requesting that Go doesn't include full file paths in the final binary... (But I guess the concern is that ldflags could contain paths if someone had a super wacky go build invocation.)

cyphar avatar Jun 21 '23 01:06 cyphar

Although by that argument, there's all sorts of other areas it could strip. Maybe the value of -X foo.Bar=abcdefg should be stripped because abcdefg might be path specific.

I think it's a case of their being too smart by half. 😁

deitch avatar Jun 21 '23 01:06 deitch