mirror of
https://github.com/golang/go
synced 2024-11-25 19:57:56 -07:00
crypto/rand: add randcrash=0 GODEBUG
For #66821 Change-Id: I525c308d6d6243a2bc805e819dcf40b67e52ade5 Reviewed-on: https://go-review.googlesource.com/c/go/+/608435 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
55b930eb07
commit
63cd5a39e9
@ -168,6 +168,11 @@ For Go 1.24, it now defaults to multipathtcp="2", thus
|
|||||||
enabled by default on listerners. Using multipathtcp="0" reverts to the
|
enabled by default on listerners. Using multipathtcp="0" reverts to the
|
||||||
pre-Go 1.24 behavior.
|
pre-Go 1.24 behavior.
|
||||||
|
|
||||||
|
Go 1.24 changed [`crypto/rand.Read`](/pkg/crypto/rand/#Read) to crash the
|
||||||
|
program on any error. This setting is controlled by the `randcrash` setting.
|
||||||
|
For Go 1.24 it defaults to `randcrash=1`.
|
||||||
|
Using `randcrash=0` reverts to the pre-Go 1.24 behavior.
|
||||||
|
|
||||||
### Go 1.23
|
### Go 1.23
|
||||||
|
|
||||||
Go 1.23 changed the channels created by package time to be unbuffered
|
Go 1.23 changed the channels created by package time to be unbuffered
|
||||||
|
@ -8,6 +8,7 @@ package rand
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/internal/boring"
|
"crypto/internal/boring"
|
||||||
|
"internal/godebug"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
@ -64,6 +65,8 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
|||||||
//go:linkname fatal
|
//go:linkname fatal
|
||||||
func fatal(string)
|
func fatal(string)
|
||||||
|
|
||||||
|
var randcrash = godebug.New("randcrash")
|
||||||
|
|
||||||
// Read fills b with cryptographically secure random bytes. It never returns an
|
// Read fills b with cryptographically secure random bytes. It never returns an
|
||||||
// error, and always fills b entirely.
|
// error, and always fills b entirely.
|
||||||
//
|
//
|
||||||
@ -83,6 +86,10 @@ func Read(b []byte) (n int, err error) {
|
|||||||
copy(b, bb)
|
copy(b, bb)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if randcrash.Value() == "0" {
|
||||||
|
randcrash.IncNonDefault()
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
fatal("crypto/rand: failed to read random data (see https://go.dev/issue/66821): " + err.Error())
|
fatal("crypto/rand: failed to read random data (see https://go.dev/issue/66821): " + err.Error())
|
||||||
panic("unreachable") // To be sure.
|
panic("unreachable") // To be sure.
|
||||||
}
|
}
|
||||||
|
@ -48,20 +48,18 @@ func TestNoGetrandom(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
cmd := testenv.Command(t, os.Args[0], "-test.v")
|
cmd := testenv.Command(t, os.Args[0], "-test.v")
|
||||||
cmd.Stdout = buf
|
|
||||||
cmd.Stderr = buf
|
|
||||||
cmd.Env = append(os.Environ(), "GO_GETRANDOM_DISABLED=1")
|
cmd.Env = append(os.Environ(), "GO_GETRANDOM_DISABLED=1")
|
||||||
if err := cmd.Run(); err != nil {
|
out, err := cmd.CombinedOutput()
|
||||||
t.Errorf("subprocess failed: %v\n%s", err, buf.Bytes())
|
if err != nil {
|
||||||
|
t.Errorf("subprocess failed: %v\n%s", err, out)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Contains(buf.Bytes(), []byte("GetRandom returned ENOSYS")) {
|
if !bytes.Contains(out, []byte("GetRandom returned ENOSYS")) {
|
||||||
t.Errorf("subprocess did not disable getrandom")
|
t.Errorf("subprocess did not disable getrandom")
|
||||||
}
|
}
|
||||||
if !bytes.Contains(buf.Bytes(), []byte("TestRead")) {
|
if !bytes.Contains(out, []byte("TestRead")) {
|
||||||
t.Errorf("subprocess did not run TestRead")
|
t.Errorf("subprocess did not run TestRead")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -8,7 +8,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/flate"
|
"compress/flate"
|
||||||
"crypto/internal/boring"
|
"crypto/internal/boring"
|
||||||
|
"errors"
|
||||||
"internal/race"
|
"internal/race"
|
||||||
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -189,6 +191,44 @@ func TestNoUrandomFallback(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadError(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping test in short mode")
|
||||||
|
}
|
||||||
|
testenv.MustHaveExec(t)
|
||||||
|
|
||||||
|
// We run this test in a subprocess because it's expected to crash the
|
||||||
|
// program unless the GODEBUG is set.
|
||||||
|
if os.Getenv("GO_TEST_READ_ERROR") == "1" {
|
||||||
|
defer func(r io.Reader) { Reader = r }(Reader)
|
||||||
|
Reader = readerFunc(func([]byte) (int, error) {
|
||||||
|
return 0, errors.New("error")
|
||||||
|
})
|
||||||
|
if _, err := Read(make([]byte, 32)); err == nil {
|
||||||
|
t.Error("Read did not return error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := testenv.Command(t, os.Args[0], "-test.run=TestReadError")
|
||||||
|
cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1")
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
t.Error("subprocess succeeded unexpectedly")
|
||||||
|
}
|
||||||
|
exp := "fatal error: crypto/rand: failed to read random data"
|
||||||
|
if !bytes.Contains(out, []byte(exp)) {
|
||||||
|
t.Errorf("subprocess output does not contain %q: %s", exp, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = testenv.Command(t, os.Args[0], "-test.run=TestReadError")
|
||||||
|
cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1", "GODEBUG=randcrash=0")
|
||||||
|
out, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("subprocess failed: %v\n%s", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkRead(b *testing.B) {
|
func BenchmarkRead(b *testing.B) {
|
||||||
b.Run("4", func(b *testing.B) {
|
b.Run("4", func(b *testing.B) {
|
||||||
benchmarkRead(b, 4)
|
benchmarkRead(b, 4)
|
||||||
|
@ -47,6 +47,7 @@ var All = []Info{
|
|||||||
{Name: "netedns0", Package: "net", Changed: 19, Old: "0"},
|
{Name: "netedns0", Package: "net", Changed: 19, Old: "0"},
|
||||||
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
|
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
|
||||||
{Name: "randautoseed", Package: "math/rand"},
|
{Name: "randautoseed", Package: "math/rand"},
|
||||||
|
{Name: "randcrash", Package: "crypto/rand", Changed: 24, Old: "0"},
|
||||||
{Name: "randseednop", Package: "math/rand", Changed: 24, Old: "0"},
|
{Name: "randseednop", Package: "math/rand", Changed: 24, Old: "0"},
|
||||||
{Name: "tarinsecurepath", Package: "archive/tar"},
|
{Name: "tarinsecurepath", Package: "archive/tar"},
|
||||||
{Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"},
|
{Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"},
|
||||||
|
@ -306,6 +306,10 @@ Below is the full list of supported metrics, ordered lexicographically.
|
|||||||
The number of non-default behaviors executed by the math/rand
|
The number of non-default behaviors executed by the math/rand
|
||||||
package due to a non-default GODEBUG=randautoseed=... setting.
|
package due to a non-default GODEBUG=randautoseed=... setting.
|
||||||
|
|
||||||
|
/godebug/non-default-behavior/randcrash:events
|
||||||
|
The number of non-default behaviors executed by the crypto/rand
|
||||||
|
package due to a non-default GODEBUG=randcrash=... setting.
|
||||||
|
|
||||||
/godebug/non-default-behavior/randseednop:events
|
/godebug/non-default-behavior/randseednop:events
|
||||||
The number of non-default behaviors executed by the math/rand
|
The number of non-default behaviors executed by the math/rand
|
||||||
package due to a non-default GODEBUG=randseednop=... setting.
|
package due to a non-default GODEBUG=randseednop=... setting.
|
||||||
|
Loading…
Reference in New Issue
Block a user