CVE-2022-30635,CVE-2022-30630,CVE-2022-30632,CVE-2022-28131, CVE-2022-30631,CVE-2022-30629,CVE-2022-30634 Conflict: NA Score: CVE-2022-32148: 5.3 CVE-2022-1962: 6.2 CVE-2022-1705: 5.3 CVE-2022-30633: 6.2 CVE-2022-30635: 5.5 CVE-2022-30630: 6.2 CVE-2022-30632: 6.2 CVE-2022-28131: 6.2 CVE-2022-30631: 7.5 CVE-2022-30629: 2.6 CVE-2022-30634: 7.5 Reference: CVE-2022-32148: https://go-review.googlesource.com/c/go/+/415221 CVE-2022-1962: https://go-review.googlesource.com/c/go/+/417070 CVE-2022-1705: https://go-review.googlesource.com/c/go/+/415217 CVE-2022-30633: https://go-review.googlesource.com/c/go/+/417069 CVE-2022-30635: https://go-review.googlesource.com/c/go/+/417074 CVE-2022-30630: https://go-review.googlesource.com/c/go/+/417072 CVE-2022-30632: https://go-review.googlesource.com/c/go/+/417073 CVE-2022-28131: https://go-review.googlesource.com/c/go/+/417068 CVE-2022-30631: https://go-review.googlesource.com/c/go/+/417071 CVE-2022-30629: https://go-review.googlesource.com/c/go/+/408574 CVE-2022-30634: https://go-review.googlesource.com/c/go/+/406635 Reason: fix CVE: CVE-2022-32148: 0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch CVE-2022-1962: 0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch CVE-2022-1705: 0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch CVE-2022-30633: 0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch CVE-2022-30635: 0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch CVE-2022-30630: 0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch CVE-2022-30632: 0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch CVE-2022-28131: 0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch CVE-2022-30631: 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch CVE-2022-30629: 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch CVE-2022-30634: 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch
247 lines
7.7 KiB
Diff
247 lines
7.7 KiB
Diff
From 07a30769186210c1b1e25943824743355c4e50f5 Mon Sep 17 00:00:00 2001
|
|
From: Roland Shoemaker <roland@golang.org>
|
|
Date: Mon, 25 Apr 2022 19:02:35 -0700
|
|
Subject: [PATCH 11/11] [release-branch.go1.17] crypto/rand: properly handle
|
|
large Read on windows
|
|
|
|
Use the batched reader to chunk large Read calls on windows to a max of
|
|
1 << 31 - 1 bytes. This prevents an infinite loop when trying to read
|
|
more than 1 << 32 -1 bytes, due to how RtlGenRandom works.
|
|
|
|
This change moves the batched function from rand_unix.go to rand.go,
|
|
since it is now needed for both windows and unix implementations.
|
|
|
|
Updates #52561
|
|
Fixes #52932
|
|
Fixes CVE-2022-30634
|
|
|
|
Change-Id: Id98fc4b1427e5cb2132762a445b2aed646a37473
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/402257
|
|
Run-TryBot: Roland Shoemaker <roland@golang.org>
|
|
Reviewed-by: Filippo Valsorda <filippo@golang.org>
|
|
Reviewed-by: Filippo Valsorda <valsorda@google.com>
|
|
TryBot-Result: Gopher Robot <gobot@golang.org>
|
|
(cherry picked from commit bb1f4416180511231de6d17a1f2f55c82aafc863)
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/406635
|
|
Reviewed-by: Damien Neil <dneil@google.com>
|
|
|
|
Conflict: NA
|
|
Reference: https://go-review.googlesource.com/c/go/+/406635
|
|
---
|
|
src/crypto/rand/rand.go | 18 ++++++++++++++++++
|
|
src/crypto/rand/rand_batched.go | 22 ++++++----------------
|
|
src/crypto/rand/rand_batched_test.go | 21 +++++++++++----------
|
|
src/crypto/rand/rand_getentropy.go | 6 +++---
|
|
src/crypto/rand/rand_unix.go | 4 ++--
|
|
src/crypto/rand/rand_windows.go | 18 ++++++------------
|
|
6 files changed, 46 insertions(+), 43 deletions(-)
|
|
|
|
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
|
|
index fddd1147e6e..f2c276008d7 100644
|
|
--- a/src/crypto/rand/rand.go
|
|
+++ b/src/crypto/rand/rand.go
|
|
@@ -23,3 +23,21 @@ var Reader io.Reader
|
|
func Read(b []byte) (n int, err error) {
|
|
return io.ReadFull(Reader, b)
|
|
}
|
|
+
|
|
+// batched returns a function that calls f to populate a []byte by chunking it
|
|
+// into subslices of, at most, readMax bytes.
|
|
+func batched(f func([]byte) error, readMax int) func([]byte) error {
|
|
+ return func(out []byte) error {
|
|
+ for len(out) > 0 {
|
|
+ read := len(out)
|
|
+ if read > readMax {
|
|
+ read = readMax
|
|
+ }
|
|
+ if err := f(out[:read]); err != nil {
|
|
+ return err
|
|
+ }
|
|
+ out = out[read:]
|
|
+ }
|
|
+ return nil
|
|
+ }
|
|
+}
|
|
diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go
|
|
index d7c5bf3562d..8df715fdd14 100644
|
|
--- a/src/crypto/rand/rand_batched.go
|
|
+++ b/src/crypto/rand/rand_batched.go
|
|
@@ -8,6 +8,7 @@
|
|
package rand
|
|
|
|
import (
|
|
+ "errors"
|
|
"internal/syscall/unix"
|
|
)
|
|
|
|
@@ -16,20 +17,6 @@ func init() {
|
|
altGetRandom = batched(getRandomBatch, maxGetRandomRead)
|
|
}
|
|
|
|
-// batched returns a function that calls f to populate a []byte by chunking it
|
|
-// into subslices of, at most, readMax bytes.
|
|
-func batched(f func([]byte) bool, readMax int) func([]byte) bool {
|
|
- return func(buf []byte) bool {
|
|
- for len(buf) > readMax {
|
|
- if !f(buf[:readMax]) {
|
|
- return false
|
|
- }
|
|
- buf = buf[readMax:]
|
|
- }
|
|
- return len(buf) == 0 || f(buf)
|
|
- }
|
|
-}
|
|
-
|
|
// If the kernel is too old to support the getrandom syscall(),
|
|
// unix.GetRandom will immediately return ENOSYS and we will then fall back to
|
|
// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS
|
|
@@ -37,7 +24,10 @@ func batched(f func([]byte) bool, readMax int) func([]byte) bool {
|
|
// If the kernel supports the getrandom() syscall, unix.GetRandom will block
|
|
// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK).
|
|
// In this case, unix.GetRandom will not return an error.
|
|
-func getRandomBatch(p []byte) (ok bool) {
|
|
+func getRandomBatch(p []byte) error {
|
|
n, err := unix.GetRandom(p, 0)
|
|
- return n == len(p) && err == nil
|
|
+ if n != len(p) {
|
|
+ return errors.New("short read")
|
|
+ }
|
|
+ return err
|
|
}
|
|
diff --git a/src/crypto/rand/rand_batched_test.go b/src/crypto/rand/rand_batched_test.go
|
|
index 2d20922c825..b56345e50f1 100644
|
|
--- a/src/crypto/rand/rand_batched_test.go
|
|
+++ b/src/crypto/rand/rand_batched_test.go
|
|
@@ -9,20 +9,21 @@ package rand
|
|
|
|
import (
|
|
"bytes"
|
|
+ "errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestBatched(t *testing.T) {
|
|
- fillBatched := batched(func(p []byte) bool {
|
|
+ fillBatched := batched(func(p []byte) error {
|
|
for i := range p {
|
|
p[i] = byte(i)
|
|
}
|
|
- return true
|
|
+ return nil
|
|
}, 5)
|
|
|
|
p := make([]byte, 13)
|
|
- if !fillBatched(p) {
|
|
- t.Fatal("batched function returned false")
|
|
+ if err := fillBatched(p); err != nil {
|
|
+ t.Fatalf("batched function returned error: %s", err)
|
|
}
|
|
expected := []byte{0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2}
|
|
if !bytes.Equal(expected, p) {
|
|
@@ -31,15 +32,15 @@ func TestBatched(t *testing.T) {
|
|
}
|
|
|
|
func TestBatchedError(t *testing.T) {
|
|
- b := batched(func(p []byte) bool { return false }, 5)
|
|
- if b(make([]byte, 13)) {
|
|
- t.Fatal("batched function should have returned false")
|
|
+ b := batched(func(p []byte) error { return errors.New("") }, 5)
|
|
+ if b(make([]byte, 13)) == nil {
|
|
+ t.Fatal("batched function should have returned an error")
|
|
}
|
|
}
|
|
|
|
func TestBatchedEmpty(t *testing.T) {
|
|
- b := batched(func(p []byte) bool { return false }, 5)
|
|
- if !b(make([]byte, 0)) {
|
|
- t.Fatal("empty slice should always return true")
|
|
+ b := batched(func(p []byte) error { return errors.New("") }, 5)
|
|
+ if err := b(make([]byte, 0)); err != nil {
|
|
+ t.Fatalf("empty slice should always return nil: %s", err)
|
|
}
|
|
}
|
|
diff --git a/src/crypto/rand/rand_getentropy.go b/src/crypto/rand/rand_getentropy.go
|
|
index dd725372ad9..b1c19f3d0da 100644
|
|
--- a/src/crypto/rand/rand_getentropy.go
|
|
+++ b/src/crypto/rand/rand_getentropy.go
|
|
@@ -15,7 +15,7 @@ func init() {
|
|
altGetRandom = getEntropy
|
|
}
|
|
|
|
-func getEntropy(p []byte) (ok bool) {
|
|
+func getEntropy(p []byte) error {
|
|
// getentropy(2) returns a maximum of 256 bytes per call
|
|
for i := 0; i < len(p); i += 256 {
|
|
end := i + 256
|
|
@@ -24,8 +24,8 @@ func getEntropy(p []byte) (ok bool) {
|
|
}
|
|
err := unix.GetEntropy(p[i:end])
|
|
if err != nil {
|
|
- return false
|
|
+ return err
|
|
}
|
|
}
|
|
- return true
|
|
+ return nil
|
|
}
|
|
diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
|
|
index 81277eb6a5d..3d11159a340 100644
|
|
--- a/src/crypto/rand/rand_unix.go
|
|
+++ b/src/crypto/rand/rand_unix.go
|
|
@@ -46,7 +46,7 @@ type devReader struct {
|
|
|
|
// altGetRandom if non-nil specifies an OS-specific function to get
|
|
// urandom-style randomness.
|
|
-var altGetRandom func([]byte) (ok bool)
|
|
+var altGetRandom func([]byte) (err error)
|
|
|
|
func warnBlocked() {
|
|
println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
|
|
@@ -59,7 +59,7 @@ func (r *devReader) Read(b []byte) (n int, err error) {
|
|
t := time.AfterFunc(60*time.Second, warnBlocked)
|
|
defer t.Stop()
|
|
}
|
|
- if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
|
|
+ if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) == nil {
|
|
return len(b), nil
|
|
}
|
|
r.mu.Lock()
|
|
diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
|
|
index 7379f1489ad..6c0655c72b6 100644
|
|
--- a/src/crypto/rand/rand_windows.go
|
|
+++ b/src/crypto/rand/rand_windows.go
|
|
@@ -9,7 +9,6 @@ package rand
|
|
|
|
import (
|
|
"internal/syscall/windows"
|
|
- "os"
|
|
)
|
|
|
|
func init() { Reader = &rngReader{} }
|
|
@@ -17,16 +16,11 @@ func init() { Reader = &rngReader{} }
|
|
type rngReader struct{}
|
|
|
|
func (r *rngReader) Read(b []byte) (n int, err error) {
|
|
- // RtlGenRandom only accepts 2**32-1 bytes at a time, so truncate.
|
|
- inputLen := uint32(len(b))
|
|
-
|
|
- if inputLen == 0 {
|
|
- return 0, nil
|
|
- }
|
|
-
|
|
- err = windows.RtlGenRandom(b)
|
|
- if err != nil {
|
|
- return 0, os.NewSyscallError("RtlGenRandom", err)
|
|
+ // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at
|
|
+ // most 1<<31-1 bytes at a time so that this works the same on 32-bit
|
|
+ // and 64-bit systems.
|
|
+ if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil {
|
|
+ return 0, err
|
|
}
|
|
- return int(inputLen), nil
|
|
+ return len(b), nil
|
|
}
|
|
--
|
|
2.30.2
|
|
|