Skip to content

Commit 73b8df2

Browse files
Merge branch 'golang:master' into master
2 parents 7653824 + 6ebb5f5 commit 73b8df2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+586
-322
lines changed

doc/godebug.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ crypto/x509.CreateCertificate. The setting `x509sha256skid=0` reverts to SHA-1.
189189
Go 1.25 corrected the semantics of contention reports for runtime-internal locks,
190190
and so removed the [`runtimecontentionstacks` setting](/pkg/runtime#hdr-Environment_Variables).
191191

192+
Go 1.25 (starting with Go 1.25 RC 2) disabled build information stamping when
193+
multiple VCS are detected due to concerns around VCS injection attacks. This
194+
behavior and setting was backported to Go 1.24.5 and Go 1.23.11. This behavior
195+
can be renabled with the setting `allowmultiplevcs=1`.
196+
192197
### Go 1.24
193198

194199
Go 1.24 added a new `fips140` setting that controls whether the Go

src/cmd/compile/doc.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ The //go:nosplit directive must be followed by a function declaration.
253253
It specifies that the function must omit its usual stack overflow check.
254254
This is most commonly used by low-level runtime code invoked
255255
at times when it is unsafe for the calling goroutine to be preempted.
256+
Using this directive outside of low-level runtime code is not safe,
257+
because it permits the nosplit function to overwrite the end of stack,
258+
leading to memory corruption and arbitrary program failure.
256259
257260
# Linkname Directive
258261

src/cmd/compile/internal/ssa/prove.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,15 +1917,22 @@ func (ft *factsTable) flowLimit(v *Value) bool {
19171917

19181918
// See if we can get any facts because v is the result of signed mod by a constant.
19191919
// The mod operation has already been rewritten, so we have to try and reconstruct it.
1920-
// x % d
1920+
//
1921+
// x % d
1922+
//
19211923
// is rewritten as
1922-
// x - (x / d) * d
1924+
//
1925+
// x - (x / d) * d
1926+
//
19231927
// furthermore, the divide itself gets rewritten. If d is a power of 2 (d == 1<<k), we do
1924-
// (x / d) * d = ((x + adj) >> k) << k
1925-
// = (x + adj) & (-1<<k)
1928+
//
1929+
// (x / d) * d = ((x + adj) >> k) << k
1930+
// = (x + adj) & (-1<<k)
1931+
//
19261932
// with adj being an adjustment in case x is negative (see below).
19271933
// if d is not a power of 2, we do
1928-
// x / d = ... TODO ...
1934+
//
1935+
// x / d = ... TODO ...
19291936
func (ft *factsTable) detectSignedMod(v *Value) bool {
19301937
if ft.detectSignedModByPowerOfTwo(v) {
19311938
return true

src/cmd/compile/internal/ssa/stmtlines_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ func TestStmtLines(t *testing.T) {
120120
break
121121
}
122122
must(err)
123+
if le.EndSequence {
124+
// When EndSequence is true only
125+
// le.Address is meaningful, skip.
126+
continue
127+
}
123128
fl := Line{le.File.Name, le.Line}
124129
lines[fl] = lines[fl] || le.IsStmt
125130
}

src/cmd/go/internal/load/pkg.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2496,7 +2496,6 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
24962496
var repoDir string
24972497
var vcsCmd *vcs.Cmd
24982498
var err error
2499-
const allowNesting = true
25002499

25012500
wantVCS := false
25022501
switch cfg.BuildBuildvcs {
@@ -2516,7 +2515,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
25162515
// (so the bootstrap toolchain packages don't even appear to be in GOROOT).
25172516
goto omitVCS
25182517
}
2519-
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
2518+
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "")
25202519
if err != nil && !errors.Is(err, os.ErrNotExist) {
25212520
setVCSError(err)
25222521
return
@@ -2539,10 +2538,11 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
25392538
}
25402539
if repoDir != "" && vcsCmd.Status != nil {
25412540
// Check that the current directory, package, and module are in the same
2542-
// repository. vcs.FromDir allows nested Git repositories, but nesting
2543-
// is not allowed for other VCS tools. The current directory may be outside
2544-
// p.Module.Dir when a workspace is used.
2545-
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
2541+
// repository. vcs.FromDir disallows nested VCS and multiple VCS in the
2542+
// same repository, unless the GODEBUG allowmultiplevcs is set. The
2543+
// current directory may be outside p.Module.Dir when a workspace is
2544+
// used.
2545+
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "")
25462546
if err != nil {
25472547
setVCSError(err)
25482548
return
@@ -2554,7 +2554,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
25542554
}
25552555
goto omitVCS
25562556
}
2557-
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
2557+
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "")
25582558
if err != nil {
25592559
setVCSError(err)
25602560
return

src/cmd/go/internal/modfetch/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func LookupLocal(ctx context.Context, codeRoot string, path string, dir string)
235235

236236
return lookupLocalCache.Do(path, func() Repo {
237237
return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
238-
repoDir, vcsCmd, err := vcs.FromDir(dir, "", true)
238+
repoDir, vcsCmd, err := vcs.FromDir(dir, "")
239239
if err != nil {
240240
return nil, err
241241
}

src/cmd/go/internal/vcs/vcs.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"errors"
1010
"fmt"
11+
"internal/godebug"
1112
"internal/lazyregexp"
1213
"internal/singleflight"
1314
"io/fs"
@@ -869,11 +870,13 @@ type vcsPath struct {
869870
schemelessRepo bool // if true, the repo pattern lacks a scheme
870871
}
871872

873+
var allowmultiplevcs = godebug.New("allowmultiplevcs")
874+
872875
// FromDir inspects dir and its parents to determine the
873876
// version control system and code repository to use.
874877
// If no repository is found, FromDir returns an error
875878
// equivalent to os.ErrNotExist.
876-
func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) {
879+
func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
877880
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
878881
dir = filepath.Clean(dir)
879882
if srcRoot != "" {
@@ -887,21 +890,28 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
887890
for len(dir) > len(srcRoot) {
888891
for _, vcs := range vcsList {
889892
if isVCSRoot(dir, vcs.RootNames) {
890-
// Record first VCS we find.
891-
// If allowNesting is false (as it is in GOPATH), keep looking for
892-
// repositories in parent directories and report an error if one is
893-
// found to mitigate VCS injection attacks.
894893
if vcsCmd == nil {
894+
// Record first VCS we find.
895895
vcsCmd = vcs
896896
repoDir = dir
897-
if allowNesting {
897+
if allowmultiplevcs.Value() == "1" {
898+
allowmultiplevcs.IncNonDefault()
898899
return repoDir, vcsCmd, nil
899900
}
901+
// If allowmultiplevcs is not set, keep looking for
902+
// repositories in current and parent directories and report
903+
// an error if one is found to mitigate VCS injection
904+
// attacks.
905+
continue
906+
}
907+
if vcsCmd == vcsGit && vcs == vcsGit {
908+
// Nested Git is allowed, as this is how things like
909+
// submodules work. Git explicitly protects against
910+
// injection against itself.
900911
continue
901912
}
902-
// Otherwise, we have one VCS inside a different VCS.
903-
return "", nil, fmt.Errorf("directory %q uses %s, but parent %q uses %s",
904-
repoDir, vcsCmd.Cmd, dir, vcs.Cmd)
913+
return "", nil, fmt.Errorf("multiple VCS detected: %s in %q, and %s in %q",
914+
vcsCmd.Cmd, repoDir, vcs.Cmd, dir)
905915
}
906916
}
907917

src/cmd/go/internal/vcs/vcs_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func TestFromDir(t *testing.T) {
239239
}
240240

241241
wantRepoDir := filepath.Dir(dir)
242-
gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
242+
gotRepoDir, gotVCS, err := FromDir(dir, tempDir)
243243
if err != nil {
244244
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
245245
continue
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# To avoid VCS injection attacks, we should not accept multiple different VCS metadata
2+
# folders within a single module (either in the same directory, or nested in different
3+
# directories.)
4+
#
5+
# This behavior should be disabled by setting the allowmultiplevcs GODEBUG.
6+
7+
[short] skip
8+
[!git] skip
9+
10+
cd samedir
11+
12+
exec git init .
13+
14+
# Without explicitly requesting buildvcs, the go command should silently continue
15+
# without determining the correct VCS.
16+
go test -c -o $devnull .
17+
18+
# If buildvcs is explicitly requested, we expect the go command to fail
19+
! go test -buildvcs -c -o $devnull .
20+
stderr '^error obtaining VCS status: multiple VCS detected:'
21+
22+
env GODEBUG=allowmultiplevcs=1
23+
go test -buildvcs -c -o $devnull .
24+
25+
env GODEBUG=
26+
cd ../nested
27+
exec git init .
28+
# cd a
29+
go test -c -o $devnull ./a
30+
! go test -buildvcs -c -o $devnull ./a
31+
stderr '^error obtaining VCS status: multiple VCS detected:'
32+
# allowmultiplevcs doesn't disable the check that the current directory, package, and
33+
# module are in the same repository.
34+
env GODEBUG=allowmultiplevcs=1
35+
! go test -buildvcs -c -o $devnull ./a
36+
stderr '^error obtaining VCS status: main package is in repository'
37+
38+
-- samedir/go.mod --
39+
module example
40+
41+
go 1.18
42+
-- samedir/example.go --
43+
package main
44+
-- samedir/.bzr/test --
45+
hello
46+
47+
-- nested/go.mod --
48+
module example
49+
50+
go 1.18
51+
-- nested/a/example.go --
52+
package main
53+
-- nested/a/.bzr/test --
54+
hello

src/cmd/go/testdata/script/version_buildvcs_nested.txt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,35 @@ cd root
99
go mod init example.com/root
1010
exec git init
1111

12-
# Nesting repositories in parent directories are ignored, as the current
13-
# directory main package, and containing main module are in the same repository.
14-
# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
15-
# we assume users have control over repositories they've checked out.
12+
13+
# Nesting repositories in parent directories are an error, to prevent VCS injection.
14+
# This can be disabled with the allowmultiplevcs GODEBUG.
1615
mkdir hgsub
1716
cd hgsub
1817
exec hg init
1918
cp ../../main.go main.go
2019
! go build
20+
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
21+
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
22+
env GODEBUG=allowmultiplevcs=1
23+
! go build
2124
stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
2225
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
2326
go build -buildvcs=false
27+
env GODEBUG=
2428
go mod init example.com/root/hgsub
29+
! go build
30+
stderr '^error obtaining VCS status: multiple VCS detected: hg in ".*hgsub", and git in ".*root"$'
31+
stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
32+
env GODEBUG=allowmultiplevcs=1
2533
go build
34+
env GODEBUG=
2635
cd ..
2736

2837
# It's an error to build a package from a nested Git repository if the package
2938
# is in a separate repository from the current directory or from the module
30-
# root directory.
39+
# root directory. Otherwise nested Git repositories are allowed, as this is
40+
# how Git implements submodules (and protects against Git based VCS injection.)
3141
mkdir gitsub
3242
cd gitsub
3343
exec git init

0 commit comments

Comments
 (0)