Skip to content
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: changes/corruption in module cache not detected #37242

Closed
bep opened this issue Feb 15, 2020 · 4 comments
Closed

cmd/go: changes/corruption in module cache not detected #37242

bep opened this issue Feb 15, 2020 · 4 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@bep
Copy link
Contributor

bep commented Feb 15, 2020

Note: to me this is a functional problem, I'm not using the "security" word.

See environment info at the bottom.

To reproduce:

Run this to generate a go.sum file

package main

import (
	"fmt"

	"github.com/bep/testmodlib"
)

func main() {
	fmt.Println(testmodlib.Hello()) // Prints "hello"

}

Then manually edit $GOPATH/pkg/mod/github.com/bep/testmodlib@v1.0.0/lib.go to make the Hello func return modified (or whatever).
¨
Then rerun the program above. It now prints `modified´.

Since I have a go.sum file for that library, I would expect the build to fail.

The reason I raise this is that I on rare occasions have seen empty cache folders. I'm not able to give further details about when/how this happens, but for me, it happens only on MacOS. In most situations, this will be visible (break the build), but not always.

uname -a && go version && go env
Darwin bep-mac16.local 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan  9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64
go version go1.13.7 darwin/amd64
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/bep/Library/Caches/go-build"
GOENV="/Users/bep/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/bep/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/bep/dev/go/bep/temp/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/wy/g1rt5g3s5bd9flpq8g1741740000gn/T/go-build844380845=/tmp/go-build -gno-record-gcc-switches -fno-common"
@mvdan
Copy link
Member

mvdan commented Feb 15, 2020

I think you're after go mod verify:

$ go help mod | grep verify
	verify      verify dependencies have expected content

I believe that other commands like go get and go build will only check a module's contents when downloading the module for the first time. Doing that again any time a build happens, or any time a module's dependencies are queried, could be pretty expensive and hurt incremental builds.

This is explained a bit in go help modules:

No matter the source of the modules, the go command checks downloads against known checksums, to detect unexpected changes in the content of any specific module version from one day to the next.

Also:

The reason I raise this is that I on rare occasions have seen empty cache folders. I'm not able to give further details about when/how this happens, but for me, it happens only on MacOS. In most situations, this will be visible (break the build), but not always.

If that is your problem, I think we should investigate it. Until the bug is investigated, go mod verify is a manual alternative.

CC @bcmills @jayconrod

@bep
Copy link
Contributor Author

bep commented Feb 15, 2020

go mod verify

I did not know about that one. Running that one on the project above gives:

github.com/bep/testmodlib v1.0.0: dir has been modified (/Users/bep/go/pkg/mod/github.com/bep/testmodlib@v1.0.0)

But I think this boils down to this:

  • I don't think you can ever give any 100% guarantee that your "download to cache" works on all platforms without additional checks.
  • Adding go mod verify as part of the build may be too heavy as part of your daily development, but certainly fine for CI/release builds.
  • Assuming "my empty folders" are empty after a `go mod download´, maybe check the folder hash after it is written ...

@jayconrod jayconrod changed the title modules: changes/corruption in module cache not detected cmd/go: changes/corruption in module cache not detected Feb 18, 2020
@jayconrod
Copy link
Contributor

Most of what you describe is working as intended.

The integrity of module zip files is verified when they are downloaded and extracted into the cache. The go command computes a cryptographic sum of the contents of each zip file and compares that to the corresponding entry in go.sum for the main module. If there is no entry in go.sum, the go command retrieves the expected sum from sum.golang.org (unless the module is in GOPRIVATE or GONOSUMDB). So we're pretty confident about the integrity of each module, when it's ingested into the cache.

Files and directories within the cache are marked read-only to prevent accidental changes (unless the -modcacherw flag is used). go mod verify may be used to compare extracted zip contents with the zip files they came from, but it would expensive to do it on every build, since it reads a lot of files that aren't normally touched.

The reason I raise this is that I on rare occasions have seen empty cache folders. I'm not able to give further details about when/how this happens, but for me, it happens only on MacOS. In most situations, this will be visible (break the build), but not always.

Assuming "my empty folders" are empty after a `go mod download´, maybe check the folder hash after it is written ...

Could you explain more? Is the whole cache empty ($GOPATH/pkg/mod)? Or a specific module directory (e.g., $GOPATH/pkg/mod/golang.org/x/tools@v0.0.0-something-something)? Or another directory? Is it right after a module is downloaded or some time later?

The go command shouldn't automatically remove anything from the module cache. go clean -modcache is the only command that would do that.

cc @bcmills @matloob

@jayconrod jayconrod added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Feb 18, 2020
@gopherbot
Copy link

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

@golang golang locked and limited conversation to collaborators Mar 18, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants