Skip to content

Commit 1cd3bf1

Browse files
authored
Merge pull request #127 from tailscale/update-go1.24.4
Update go1.24.4 6796ebb (tag: go1.24.4, go/release-branch.go1.24) [release-branch.go1.24] go1.24.4 85897ca [release-branch.go1.24] net/http: strip sensitive proxy headers from redirect requests 9f9cf28 [release-branch.go1.24] os: don't follow symlinks on Windows when O_CREATE|O_EXCL a31c931 [release-branch.go1.24] cmd/link: allow linkname reference to a TEXT symbol regardless of size 03811ab [release-branch.go1.24] crypto/x509: decouple key usage and policy validation 04a9473 [release-branch.go1.24] lib/fips140: set inprocess.txt to v1.0.0 db8f1dc [release-branch.go1.24] hash/maphash: hash channels in purego version of maphash.Comparable 664cf83 [release-branch.go1.24] runtime/debug: document DefaultGODEBUG as a BuildSetting
2 parents 98e8c99 + ba4b7a7 commit 1cd3bf1

File tree

16 files changed

+181
-50
lines changed

16 files changed

+181
-50
lines changed

VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
go1.24.3
2-
time 2025-04-30T18:13:34Z
1+
go1.24.4
2+
time 2025-05-29T19:37:36Z

lib/fips140/inprocess.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v1.0.0

src/cmd/link/internal/loader/loader.go

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -452,33 +452,50 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
452452
if oldsym.Dupok() {
453453
return oldi
454454
}
455-
// If one is a DATA symbol (i.e. has content, DataSize != 0)
456-
// and the other is BSS, the one with content wins.
455+
// If one is a DATA symbol (i.e. has content, DataSize != 0,
456+
// including RODATA) and the other is BSS, the one with content wins.
457457
// If both are BSS, the one with larger size wins.
458-
// Specifically, the "overwrite" variable and the final result are
459458
//
460-
// new sym old sym overwrite
459+
// For a special case, we allow a TEXT symbol overwrites a BSS symbol
460+
// even if the BSS symbol has larger size. This is because there is
461+
// code like below to take the address of a function
462+
//
463+
// //go:linkname fn
464+
// var fn uintptr
465+
// var fnAddr = uintptr(unsafe.Pointer(&fn))
466+
//
467+
// TODO: maybe limit this case to just pointer sized variable?
468+
//
469+
// In summary, the "overwrite" variable and the final result are
470+
//
471+
// new sym old sym result
461472
// ---------------------------------------------
462-
// DATA DATA true => ERROR
463-
// DATA lg/eq BSS sm/eq true => new wins
464-
// DATA small BSS large true => ERROR
465-
// BSS large DATA small true => ERROR
466-
// BSS large BSS small true => new wins
467-
// BSS sm/eq D/B lg/eq false => old wins
468-
overwrite := r.DataSize(li) != 0 || oldsz < sz
469-
if overwrite {
473+
// TEXT BSS new wins
474+
// DATA DATA ERROR
475+
// DATA lg/eq BSS sm/eq new wins
476+
// DATA small BSS large ERROR
477+
// BSS large DATA small ERROR
478+
// BSS large BSS small new wins
479+
// BSS sm/eq D/B lg/eq old wins
480+
// BSS TEXT old wins
481+
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
482+
newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
483+
oldIsText := oldtyp.IsText()
484+
newIsText := newtyp.IsText()
485+
oldHasContent := oldr.DataSize(oldli) != 0
486+
newHasContent := r.DataSize(li) != 0
487+
oldIsBSS := oldtyp.IsData() && !oldHasContent
488+
newIsBSS := newtyp.IsData() && !newHasContent
489+
switch {
490+
case newIsText && oldIsBSS,
491+
newHasContent && oldIsBSS && sz >= oldsz,
492+
newIsBSS && oldIsBSS && sz > oldsz:
470493
// new symbol overwrites old symbol.
471-
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
472-
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) || oldsz > sz {
473-
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
474-
}
475494
l.objSyms[oldi] = objSym{r.objidx, li}
476-
} else {
477-
// old symbol overwrites new symbol.
478-
typ := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
479-
if !typ.IsData() { // only allow overwriting data symbol
480-
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
481-
}
495+
case newIsBSS && (oldsz >= sz || oldIsText):
496+
// old win, just ignore the new symbol.
497+
default:
498+
log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
482499
}
483500
return oldi
484501
}

src/cmd/link/link_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,9 @@ func TestCheckLinkname(t *testing.T) {
15121512
{"ok.go", true},
15131513
// push linkname is ok
15141514
{"push.go", true},
1515+
// using a linknamed variable to reference an assembly
1516+
// function in the same package is ok
1517+
{"textvar", true},
15151518
// pull linkname of blocked symbol is not ok
15161519
{"coro.go", false},
15171520
{"coro_var.go", false},
@@ -1529,7 +1532,7 @@ func TestCheckLinkname(t *testing.T) {
15291532
test := test
15301533
t.Run(test.src, func(t *testing.T) {
15311534
t.Parallel()
1532-
src := filepath.Join("testdata", "linkname", test.src)
1535+
src := "./testdata/linkname/" + test.src
15331536
exe := filepath.Join(tmpdir, test.src+".exe")
15341537
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src)
15351538
out, err := cmd.CombinedOutput()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
TEXT ·asmfunc(SB),0,$0-0
6+
RET
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Using a linknamed variable to reference an assembly
6+
// function in the same package is ok.
7+
8+
package main
9+
10+
import _ "unsafe"
11+
12+
func main() {
13+
println(&asmfunc)
14+
}
15+
16+
//go:linkname asmfunc
17+
var asmfunc uintptr

src/crypto/x509/verify.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -841,31 +841,45 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
841841
}
842842
}
843843

844-
if len(opts.KeyUsages) == 0 {
845-
opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
844+
chains = make([][]*Certificate, 0, len(candidateChains))
845+
846+
var invalidPoliciesChains int
847+
for _, candidate := range candidateChains {
848+
if !policiesValid(candidate, opts) {
849+
invalidPoliciesChains++
850+
continue
851+
}
852+
chains = append(chains, candidate)
853+
}
854+
855+
if len(chains) == 0 {
856+
return nil, CertificateInvalidError{c, NoValidChains, "all candidate chains have invalid policies"}
846857
}
847858

848859
for _, eku := range opts.KeyUsages {
849860
if eku == ExtKeyUsageAny {
850861
// If any key usage is acceptable, no need to check the chain for
851862
// key usages.
852-
return candidateChains, nil
863+
return chains, nil
853864
}
854865
}
855866

856-
chains = make([][]*Certificate, 0, len(candidateChains))
857-
var incompatibleKeyUsageChains, invalidPoliciesChains int
867+
if len(opts.KeyUsages) == 0 {
868+
opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
869+
}
870+
871+
candidateChains = chains
872+
chains = chains[:0]
873+
874+
var incompatibleKeyUsageChains int
858875
for _, candidate := range candidateChains {
859876
if !checkChainForKeyUsage(candidate, opts.KeyUsages) {
860877
incompatibleKeyUsageChains++
861878
continue
862879
}
863-
if !policiesValid(candidate, opts) {
864-
invalidPoliciesChains++
865-
continue
866-
}
867880
chains = append(chains, candidate)
868881
}
882+
869883
if len(chains) == 0 {
870884
var details []string
871885
if incompatibleKeyUsageChains > 0 {

src/crypto/x509/verify_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,3 +3012,39 @@ func TestPoliciesValid(t *testing.T) {
30123012
})
30133013
}
30143014
}
3015+
3016+
func TestInvalidPolicyWithAnyKeyUsage(t *testing.T) {
3017+
loadTestCert := func(t *testing.T, path string) *Certificate {
3018+
b, err := os.ReadFile(path)
3019+
if err != nil {
3020+
t.Fatal(err)
3021+
}
3022+
p, _ := pem.Decode(b)
3023+
c, err := ParseCertificate(p.Bytes)
3024+
if err != nil {
3025+
t.Fatal(err)
3026+
}
3027+
return c
3028+
}
3029+
3030+
testOID3 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 3})
3031+
root, intermediate, leaf := loadTestCert(t, "testdata/policy_root.pem"), loadTestCert(t, "testdata/policy_intermediate_require.pem"), loadTestCert(t, "testdata/policy_leaf.pem")
3032+
3033+
expectedErr := "x509: no valid chains built: all candidate chains have invalid policies"
3034+
3035+
roots, intermediates := NewCertPool(), NewCertPool()
3036+
roots.AddCert(root)
3037+
intermediates.AddCert(intermediate)
3038+
3039+
_, err := leaf.Verify(VerifyOptions{
3040+
Roots: roots,
3041+
Intermediates: intermediates,
3042+
KeyUsages: []ExtKeyUsage{ExtKeyUsageAny},
3043+
CertificatePolicies: []OID{testOID3},
3044+
})
3045+
if err == nil {
3046+
t.Fatal("unexpected success, invalid policy shouldn't be bypassed by passing VerifyOptions.KeyUsages with ExtKeyUsageAny")
3047+
} else if err.Error() != expectedErr {
3048+
t.Fatalf("unexpected error, got %q, want %q", err, expectedErr)
3049+
}
3050+
}

src/hash/maphash/maphash_purego.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func appendT(h *Hash, v reflect.Value) {
161161
case reflect.Bool:
162162
h.WriteByte(btoi(v.Bool()))
163163
return
164-
case reflect.UnsafePointer, reflect.Pointer:
164+
case reflect.UnsafePointer, reflect.Pointer, reflect.Chan:
165165
var buf [8]byte
166166
// because pointing to the abi.Escape call in comparableReady,
167167
// So this is ok to hash pointer,

src/hash/maphash/maphash_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,17 @@ func TestComparable(t *testing.T) {
253253
}
254254
testComparable(t, s1, s2)
255255
testComparable(t, s1.s, s2.s)
256+
c1 := make(chan struct{})
257+
c2 := make(chan struct{})
258+
testComparable(t, c1, c1)
259+
testComparable(t, chan struct{}(nil))
256260
testComparable(t, float32(0), negativeZero[float32]())
257261
testComparable(t, float64(0), negativeZero[float64]())
258262
testComparableNoEqual(t, math.NaN(), math.NaN())
259263
testComparableNoEqual(t, [2]string{"a", ""}, [2]string{"", "a"})
260264
testComparableNoEqual(t, struct{ a, b string }{"foo", ""}, struct{ a, b string }{"", "foo"})
261265
testComparableNoEqual(t, struct{ a, b any }{int(0), struct{}{}}, struct{ a, b any }{struct{}{}, int(0)})
266+
testComparableNoEqual(t, c1, c2)
262267
}
263268

264269
func testComparableNoEqual[T comparable](t *testing.T, v1, v2 T) {

src/internal/syscall/windows/at_windows.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func Openat(dirfd syscall.Handle, name string, flag int, perm uint32) (_ syscall
8888
switch {
8989
case flag&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
9090
disposition = FILE_CREATE
91+
options |= FILE_OPEN_REPARSE_POINT // don't follow symlinks
9192
case flag&syscall.O_CREAT == syscall.O_CREAT:
9293
disposition = FILE_OPEN_IF
9394
default:

src/net/http/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,8 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensit
805805
for k, vv := range ireqhdr {
806806
sensitive := false
807807
switch CanonicalHeaderKey(k) {
808-
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
808+
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2",
809+
"Proxy-Authorization", "Proxy-Authenticate":
809810
sensitive = true
810811
}
811812
if !(sensitive && stripSensitiveHeaders) {

src/net/http/client_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,8 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
15471547
if r.Host+r.URL.Path != "a.example.com/" {
15481548
if h := r.Header.Get("Authorization"); h != "" {
15491549
t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h)
1550+
} else if h := r.Header.Get("Proxy-Authorization"); h != "" {
1551+
t.Errorf("on request to %v%v, Proxy-Authorization=%q, want no header", r.Host, r.URL.Path, h)
15501552
}
15511553
}
15521554
// Follow a chain of redirects from a to b and back to a.
@@ -1575,6 +1577,7 @@ func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
15751577
req, _ := NewRequest("GET", proto+"://a.example.com/", nil)
15761578
req.Header.Add("Cookie", "foo=bar")
15771579
req.Header.Add("Authorization", "secretpassword")
1580+
req.Header.Add("Proxy-Authorization", "secretpassword")
15781581
res, err := c.Do(req)
15791582
if err != nil {
15801583
t.Fatal(err)

src/os/os_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,31 @@ func TestFilePermissions(t *testing.T) {
22232223

22242224
}
22252225

2226+
func TestOpenFileCreateExclDanglingSymlink(t *testing.T) {
2227+
testMaybeRooted(t, func(t *testing.T, r *Root) {
2228+
const link = "link"
2229+
if err := Symlink("does_not_exist", link); err != nil {
2230+
t.Fatal(err)
2231+
}
2232+
var f *File
2233+
var err error
2234+
if r == nil {
2235+
f, err = OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
2236+
} else {
2237+
f, err = r.OpenFile(link, O_WRONLY|O_CREATE|O_EXCL, 0o444)
2238+
}
2239+
if err == nil {
2240+
f.Close()
2241+
}
2242+
if !errors.Is(err, ErrExist) {
2243+
t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL = %v, want ErrExist", err)
2244+
}
2245+
if _, err := Stat(link); err == nil {
2246+
t.Errorf("OpenFile of a dangling symlink with O_CREATE|O_EXCL created a file")
2247+
}
2248+
})
2249+
}
2250+
22262251
// TestFileRDWRFlags tests the O_RDONLY, O_WRONLY, and O_RDWR flags.
22272252
func TestFileRDWRFlags(t *testing.T) {
22282253
for _, test := range []struct {

src/runtime/debug/mod.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ type Module struct {
8686
// - CGO_CPPFLAGS: the effective CGO_CPPFLAGS environment variable
8787
// - CGO_CXXFLAGS: the effective CGO_CXXFLAGS environment variable
8888
// - CGO_LDFLAGS: the effective CGO_LDFLAGS environment variable
89+
// - DefaultGODEBUG: the effective GODEBUG settings
8990
// - GOARCH: the architecture target
9091
// - GOAMD64/GOARM/GO386/etc: the architecture feature level for GOARCH
9192
// - GOOS: the operating system target

src/syscall/syscall_windows.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -376,20 +376,6 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
376376
if flag&O_CLOEXEC == 0 {
377377
sa = makeInheritSa()
378378
}
379-
// We don't use CREATE_ALWAYS, because when opening a file with
380-
// FILE_ATTRIBUTE_READONLY these will replace an existing file
381-
// with a new, read-only one. See https://go.dev/issue/38225.
382-
//
383-
// Instead, we ftruncate the file after opening when O_TRUNC is set.
384-
var createmode uint32
385-
switch {
386-
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
387-
createmode = CREATE_NEW
388-
case flag&O_CREAT == O_CREAT:
389-
createmode = OPEN_ALWAYS
390-
default:
391-
createmode = OPEN_EXISTING
392-
}
393379
var attrs uint32 = FILE_ATTRIBUTE_NORMAL
394380
if perm&S_IWRITE == 0 {
395381
attrs = FILE_ATTRIBUTE_READONLY
@@ -404,6 +390,21 @@ func Open(name string, flag int, perm uint32) (fd Handle, err error) {
404390
const _FILE_FLAG_WRITE_THROUGH = 0x80000000
405391
attrs |= _FILE_FLAG_WRITE_THROUGH
406392
}
393+
// We don't use CREATE_ALWAYS, because when opening a file with
394+
// FILE_ATTRIBUTE_READONLY these will replace an existing file
395+
// with a new, read-only one. See https://go.dev/issue/38225.
396+
//
397+
// Instead, we ftruncate the file after opening when O_TRUNC is set.
398+
var createmode uint32
399+
switch {
400+
case flag&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
401+
createmode = CREATE_NEW
402+
attrs |= FILE_FLAG_OPEN_REPARSE_POINT // don't follow symlinks
403+
case flag&O_CREAT == O_CREAT:
404+
createmode = OPEN_ALWAYS
405+
default:
406+
createmode = OPEN_EXISTING
407+
}
407408
h, err := createFile(namep, access, sharemode, sa, createmode, attrs, 0)
408409
if h == InvalidHandle {
409410
if err == ERROR_ACCESS_DENIED && (flag&O_WRONLY != 0 || flag&O_RDWR != 0) {

0 commit comments

Comments
 (0)