1
0
mirror of https://github.com/golang/go synced 2024-11-14 21:00:28 -07:00

[release-branch.go1.15-security] cmd/go: pass resolved CC, GCCGO to cgo

This makes sure the go command and cgo agree about
exactly which compiler is being used.

This issue was reported by RyotaK.

Fixes CVE-2021-3115.

Change-Id: If171c5c8b2523efb5ea2d957e5ad1380a038149c
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/949416
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
(cherry picked from commit 4cf399ca38587a6e4a3e85b494cd9a9b4cc53378)
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/955293
Reviewed-by: Katie Hockman <katiehockman@google.com>
This commit is contained in:
Russ Cox 2021-01-11 09:41:54 -05:00 committed by Roland Shoemaker
parent 5c8fd727c4
commit e8e7facfaa
2 changed files with 26 additions and 7 deletions

View File

@ -56,6 +56,9 @@ type Builder struct {
id sync.Mutex id sync.Mutex
toolIDCache map[string]string // tool name -> tool ID toolIDCache map[string]string // tool name -> tool ID
buildIDCache map[string]string // file name -> build ID buildIDCache map[string]string // file name -> build ID
cgoEnvOnce sync.Once
cgoEnvCache []string
} }
// NOTE: Much of Action would not need to be exported if not for test. // NOTE: Much of Action would not need to be exported if not for test.

View File

@ -1080,10 +1080,8 @@ func (b *Builder) vet(a *Action) error {
return err return err
} }
env := b.cCompilerEnv() // TODO(rsc): Why do we pass $GCCGO to go vet?
if cfg.BuildToolchainName == "gccgo" { env := b.cgoEnv()
env = append(env, "GCCGO="+BuildToolchain.compiler())
}
p := a.Package p := a.Package
tool := VetTool tool := VetTool
@ -2014,6 +2012,24 @@ func (b *Builder) cCompilerEnv() []string {
return []string{"TERM=dumb"} return []string{"TERM=dumb"}
} }
// cgoEnv returns environment variables to set when running cgo.
// Some of these pass through to cgo running the C compiler,
// so it includes cCompilerEnv.
func (b *Builder) cgoEnv() []string {
b.cgoEnvOnce.Do(func() {
cc, err := exec.LookPath(b.ccExe()[0])
if err != nil || filepath.Base(cc) == cc { // reject relative path
cc = "/missing-cc"
}
gccgo := GccgoBin
if filepath.Base(gccgo) == gccgo { // reject relative path
gccgo = "/missing-gccgo"
}
b.cgoEnvCache = append(b.cCompilerEnv(), "CC="+cc, "GCCGO="+gccgo)
})
return b.cgoEnvCache
}
// mkdir makes the named directory. // mkdir makes the named directory.
func (b *Builder) Mkdir(dir string) error { func (b *Builder) Mkdir(dir string) error {
// Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "". // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
@ -2603,13 +2619,13 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
// along to the host linker. At this point in the code, cgoLDFLAGS // along to the host linker. At this point in the code, cgoLDFLAGS
// consists of the original $CGO_LDFLAGS (unchecked) and all the // consists of the original $CGO_LDFLAGS (unchecked) and all the
// flags put together from source code (checked). // flags put together from source code (checked).
cgoenv := b.cCompilerEnv() cgoenv := b.cgoEnv()
if len(cgoLDFLAGS) > 0 { if len(cgoLDFLAGS) > 0 {
flags := make([]string, len(cgoLDFLAGS)) flags := make([]string, len(cgoLDFLAGS))
for i, f := range cgoLDFLAGS { for i, f := range cgoLDFLAGS {
flags[i] = strconv.Quote(f) flags[i] = strconv.Quote(f)
} }
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
} }
if cfg.BuildToolchainName == "gccgo" { if cfg.BuildToolchainName == "gccgo" {
@ -2824,7 +2840,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
if p.Standard && p.ImportPath == "runtime/cgo" { if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = []string{"-dynlinker"} // record path to dynamic linker cgoflags = []string{"-dynlinker"} // record path to dynamic linker
} }
return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) return b.run(a, p.Dir, p.ImportPath, b.cgoEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
} }
// Run SWIG on all SWIG input files. // Run SWIG on all SWIG input files.