Skip to content

cmd/go: any invocation creates read-only telemetry configuration file under GOMODCACHE #68946

@chrisnovakovic

Description

@chrisnovakovic

Go version

go version go1.23.0 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/.cache/go-build'
GOENV='/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/csn/please-go-rules/plz-out/bin/third_party/go/toolchain'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/csn/please-go-rules/plz-out/bin/third_party/go/toolchain/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.0'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/csn/please-go-rules/plz-out/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/home/csn/please-go-rules/plz-out/tmp/test/root_test/root_test._test/run_1/go-build1923171216=/tmp/go-build -gno-record-gcc-switches'

What did you do?

The Please build system performs build actions in an environment that is isolated from the host system as much as possible. In particular, the inputs for a build action are linked into a temporary directory, and the build action's environment is sanitised - you'll notice the impact this has on the Go environment in the output of go env above. The go-rules plugin contains build definitions for compiling Go code with a Go toolchain, similarly to Bazel's rules_go.

After bumping go-rules' Go toolchain to 1.23.0, we've run into a situation where Please can't clean up the temporary directory it creates after a target has been built:

28 test targets and 78 tests run; 75 passed, 1 errored, 2 skipped.
Total time: 2m18.18s real, 5m33.79s compute.
Messages:
19:36:15.239 WARNING: Failed to remove temporary directory for //tools/please_go/install/exec:exec: failed to remove plz-out/tmp/tools/please_go/install/exec/exec._build: exit status 1
Output: rm: cannot remove 'plz-out/tmp/tools/please_go/install/exec/exec._build/pkg/mod/cache/download/golang.org/x/telemetry/config/@v': Directory not empty
19:36:19.065 WARNING: Failed to remove test directory for //tools/please_go/install:install_test: failed to remove plz-out/tmp/tools/please_go/install/install_test._test/run_1: exit status 1
Output: rm: cannot remove 'plz-out/tmp/tools/please_go/install/install_test._test/run_1/go/pkg/mod/golang.org/x/telemetry/config@v0.29.0/doc.go': Permission denied
rm: cannot remove 'plz-out/tmp/tools/please_go/install/install_test._test/run_1/go/pkg/mod/golang.org/x/telemetry/config@v0.29.0/LICENSE': Permission denied
rm: cannot remove 'plz-out/tmp/tools/please_go/install/install_test._test/run_1/go/pkg/mod/golang.org/x/telemetry/config@v0.29.0/config.json':Permission denied
rm: cannot remove 'plz-out/tmp/tools/please_go/install/install_test._test/run_1/go/pkg/mod/golang.org/x/telemetry/config@v0.29.0/go.mod': Permission denied

The root cause of this is that, by default, any invocation of go causes x/telemetry/internal/configstore to pull the latest telemetry configuration from x/telemetry/config via go mod download without using the -modcacherw flag:

https://github.com/golang/telemetry/blob/0693e6240b9b888df93a2e280a64431c10d47a63/internal/configstore/download.go#L43

Because this writes the configuration beneath GOROOT with 0444 permissions (and with 0555 intermediate directories), Please is prevented from unlinking the entire temporary directory tree.

I'm aware that telemetry can be disabled by writing off to $HOME/.config/go/telemetry before running go, which prevents this module from being pulled in the first place. However, the value of HOME is also set to the path to the temporary directory so this would have to be done before every invocation of go inside the build sandbox - while we could guarantee that this happens for the build definitions in the go-rules plugin, it's impossible to guarantee in the general case, where users write custom build rules that run whatever commands they want.

What did you see happen?

Please builds the target, but isn't able to clean up its own temporary directory afterwards owing to the Go toolchain writing a read-only file tree beneath GOROOT.

What did you expect to see?

Please builds the target and is able to clean up its own temporary directory afterwards without having to resort to hacks such as running go clean -modcache or chmodding GOROOT to make every file within it writeable after every invocation of go.

Metadata

Metadata

Assignees

Labels

CriticalA critical problem that affects the availability or correctness of production systems built using GoGoCommandcmd/goNeedsFixThe path to resolution is known, but the work has not been done.telemetryx/telemetry issues

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions