]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: pass resolved CC, GCCGO to cgo
authorRuss Cox <rsc@golang.org>
Mon, 11 Jan 2021 14:41:54 +0000 (09:41 -0500)
committerRoland Shoemaker <roland@golang.org>
Thu, 21 Jan 2021 19:08:04 +0000 (19:08 +0000)
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
Fixes #43783

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>
Reviewed-on: https://go-review.googlesource.com/c/go/+/284780
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Roland Shoemaker <roland@golang.org>

src/cmd/go/internal/work/action.go
src/cmd/go/internal/work/exec.go

index 9d141ae233dfcdb1410d3633007f5698ea2a0365..b071ed14008e8d8e8dbbda4779d897d9339f8bf8 100644 (file)
@@ -57,6 +57,9 @@ type Builder struct {
        id           sync.Mutex
        toolIDCache  map[string]string // tool name -> tool 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.
index af8b78e6618e78576ec521b19d02c267dae0da01..e7509042667409aff9fa5e210109bef6ddadd696 100644 (file)
@@ -1164,10 +1164,8 @@ func (b *Builder) vet(ctx context.Context, a *Action) error {
                return err
        }
 
-       env := b.cCompilerEnv()
-       if cfg.BuildToolchainName == "gccgo" {
-               env = append(env, "GCCGO="+BuildToolchain.compiler())
-       }
+       // TODO(rsc): Why do we pass $GCCGO to go vet?
+       env := b.cgoEnv()
 
        p := a.Package
        tool := VetTool
@@ -2110,6 +2108,24 @@ func (b *Builder) cCompilerEnv() []string {
        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.
 func (b *Builder) Mkdir(dir string) error {
        // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
@@ -2710,13 +2726,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
        // consists of the original $CGO_LDFLAGS (unchecked) and all the
        // flags put together from source code (checked).
-       cgoenv := b.cCompilerEnv()
+       cgoenv := b.cgoEnv()
        if len(cgoLDFLAGS) > 0 {
                flags := make([]string, len(cgoLDFLAGS))
                for i, f := range cgoLDFLAGS {
                        flags[i] = strconv.Quote(f)
                }
-               cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
+               cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
        }
 
        if cfg.BuildToolchainName == "gccgo" {
@@ -2947,7 +2963,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
        if p.Standard && p.ImportPath == "runtime/cgo" {
                cgoflags = []string{"-dynlinker"} // record path to dynamic linker
        }
-       return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
+       return b.run(a, base.Cwd, p.ImportPath, b.cgoEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
 }
 
 // Run SWIG on all SWIG input files.