已开启
fix: CVE-2026-33818 - openEuler-24.03-LTS-SP3 #648
xiaoo_robot创建于 8月17日
fix: CVE-2026-33818 - openEuler-24.03-LTS-SP3 #648
已开启
共 2 个文件变更+207-1
| @@ -0,0 +1,199 @@ | |||
| 1 | +From 8d01cbaad59021bd6d4f6e2dd864413872434250 Mon Sep 17 00:00:00 2001 | ||
| 2 | +From: Ian Alexander <jitsu@google.com> | ||
| 3 | +Date: Mon, 8 Jun 2026 12:56:36 -0400 | ||
| 4 | +Subject: [PATCH] [release-branch.go1.25] encoding/asn1: enforce maximum | ||
| 5 | + recursion depth | ||
| 6 | + | ||
| 7 | +Enforce a recursion limit in Unmarshal to prevent stack exhaustion when | ||
| 8 | +parsing deeply-nested, recursive structures. | ||
| 9 | + | ||
| 10 | +Thanks to Marwan Atia (marwansamir688@gmail.com) for reporting this | ||
| 11 | +issue. | ||
| 12 | + | ||
| 13 | +Fixes CVE-2026-33818 | ||
| 14 | +Fixes #80405 | ||
| 15 | + | ||
| 16 | +Change-Id: Ic78d104432f8665a2949b95935fea23b5e35cff7 | ||
| 17 | +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/4780 | ||
| 18 | +Reviewed-by: Neal Patel <nealpatel@google.com> | ||
| 19 | +Reviewed-by: Damien Neil <dneil@google.com> | ||
| 20 | +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/5261 | ||
| 21 | +Reviewed-on: https://go-review.googlesource.com/c/go/+/814820 | ||
| 22 | +Reviewed-by: Mark Freeman <mark@golang.org> | ||
| 23 | +TryBot-Bypass: Gopher Robot <gobot@golang.org> | ||
| 24 | +Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> | ||
| 25 | +Auto-Submit: Gopher Robot <gobot@golang.org> | ||
| 26 | +Conflict: Adapt context | ||
| 27 | +--- | ||
| 28 | + src/encoding/asn1/asn1.go | 21 +++++++--- | ||
| 29 | + src/encoding/asn1/asn1_test.go | 87 ++++++++++++++++++++++++++++++++++++++++++ | ||
| 30 | + 2 files changed, 102 insertions(+), 6 deletions(-) | ||
| 31 | +diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go | ||
| 32 | +index f4d0dd1..95a7031 100644 | ||
| 33 | +--- a/src/encoding/asn1/asn1.go | ||
| 34 | ++++ b/src/encoding/asn1/asn1.go | ||
| 35 | + import ( | ||
| 36 | + "math" | ||
| 37 | + "math/big" | ||
| 38 | + "reflect" | ||
| 39 | ++ "runtime" | ||
| 40 | + "strconv" | ||
| 41 | + "strings" | ||
| 42 | + "time" | ||
| 43 | + func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i | ||
| 44 | + // parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse | ||
| 45 | + // a number of ASN.1 values from the given byte slice and returns them as a | ||
| 46 | + // slice of Go values of the given type. | ||
| 47 | +-func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) { | ||
| 48 | ++func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type, depth int) (ret reflect.Value, err error) { | ||
| 49 | + matchAny, expectedTag, compoundType, ok := getUniversalType(elemType) | ||
| 50 | + if !ok { | ||
| 51 | + err = StructuralError{"unknown Go type for slice"} | ||
| 52 | + func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type | ||
| 53 | + offset := 0 | ||
| 54 | + for i := 0; i < numElements; i++ { | ||
| 55 | + ret = reflect.Append(ret, reflect.Zero(elemType)) | ||
| 56 | +- offset, err = parseField(ret.Index(i), bytes, offset, params) | ||
| 57 | ++ offset, err = parseField(ret.Index(i), bytes, offset, params, depth) | ||
| 58 | + if err != nil { | ||
| 59 | + return | ||
| 60 | + } | ||
| 61 | + func invalidLength(offset, length, sliceLength int) bool { | ||
| 62 | + // parseField is the main parsing function. Given a byte slice and an offset | ||
| 63 | + // into the array, it will try to parse a suitable ASN.1 value out and store it | ||
| 64 | + // in the given Value. | ||
| 65 | +-func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) { | ||
| 66 | ++func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters, depth int) (offset int, err error) { | ||
| 67 | ++ depth++ | ||
| 68 | ++ const ( | ||
| 69 | ++ maxDecodeDepth = 10000 | ||
| 70 | ++ maxDecodeDepthWasm = 5000 // go.dev/issue/56498 | ||
| 71 | ++ ) | ||
| 72 | ++ if depth > maxDecodeDepth || runtime.GOARCH == "wasm" && depth > maxDecodeDepthWasm { | ||
| 73 | ++ return initOffset, StructuralError{"nesting depth exceeded"} | ||
| 74 | ++ } | ||
| 75 | + offset = initOffset | ||
| 76 | + fieldType := v.Type() | ||
| 77 | + | ||
| 78 | + func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam | ||
| 79 | + if i == 0 && field.Type == rawContentsType { | ||
| 80 | + continue | ||
| 81 | + } | ||
| 82 | +- innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1"))) | ||
| 83 | ++ innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")), depth) | ||
| 84 | + if err != nil { | ||
| 85 | + return | ||
| 86 | + } | ||
| 87 | + func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam | ||
| 88 | + reflect.Copy(val, reflect.ValueOf(innerBytes)) | ||
| 89 | + return | ||
| 90 | + } | ||
| 91 | +- newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) | ||
| 92 | ++ newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem(), depth) | ||
| 93 | + if err1 == nil { | ||
| 94 | + val.Set(newSlice) | ||
| 95 | + } | ||
| 96 | + func UnmarshalWithParams(b []byte, val any, params string) (rest []byte, err err | ||
| 97 | + if v.Kind() != reflect.Pointer || v.IsNil() { | ||
| 98 | + return nil, &invalidUnmarshalError{reflect.TypeOf(val)} | ||
| 99 | + } | ||
| 100 | +- offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params)) | ||
| 101 | ++ offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params), 0) | ||
| 102 | + if err != nil { | ||
| 103 | + return nil, err | ||
| 104 | + } | ||
| 105 | +diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go | ||
| 106 | +index 249d4e4..fca2e9d 100644 | ||
| 107 | +--- a/src/encoding/asn1/asn1_test.go | ||
| 108 | ++++ b/src/encoding/asn1/asn1_test.go | ||
| 109 | + func TestParsingMemoryConsumption(t *testing.T) { | ||
| 110 | + t.Errorf("Too much memory allocated while parsing DER: %v MiB", memDiff/1024/1024) | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | ++ | ||
| 114 | ++func TestUnmarshalNestingLimitSlice(t *testing.T) { | ||
| 115 | ++ type Recursive []Recursive | ||
| 116 | ++ | ||
| 117 | ++ limit := 10000 | ||
| 118 | ++ if runtime.GOARCH == "wasm" { | ||
| 119 | ++ limit = 5000 | ||
| 120 | ++ } | ||
| 121 | ++ | ||
| 122 | ++ makeData := func(t *testing.T, depth int) []byte { | ||
| 123 | ++ var r Recursive | ||
| 124 | ++ for range depth - 1 { | ||
| 125 | ++ r = Recursive{r} | ||
| 126 | ++ } | ||
| 127 | ++ data, err := Marshal(r) | ||
| 128 | ++ if err != nil { | ||
| 129 | ++ t.Fatalf("Marshal failed: %v", err) | ||
| 130 | ++ } | ||
| 131 | ++ return data | ||
| 132 | ++ } | ||
| 133 | ++ | ||
| 134 | ++ t.Run("below limit", func(t *testing.T) { | ||
| 135 | ++ data := makeData(t, limit) | ||
| 136 | ++ var r Recursive | ||
| 137 | ++ if _, err := Unmarshal(data, &r); err != nil { | ||
| 138 | ++ t.Errorf("Unmarshal failed at depth %d: %v", limit, err) | ||
| 139 | ++ } | ||
| 140 | ++ }) | ||
| 141 | ++ | ||
| 142 | ++ t.Run("above limit", func(t *testing.T) { | ||
| 143 | ++ data := makeData(t, limit+1) | ||
| 144 | ++ var r Recursive | ||
| 145 | ++ _, err := Unmarshal(data, &r) | ||
| 146 | ++ if err == nil { | ||
| 147 | ++ t.Fatalf("Unmarshal succeeded at depth %d, want error", limit+1) | ||
| 148 | ++ } | ||
| 149 | ++ if got, want := err.Error(), "asn1: structure error: nesting depth exceeded"; got != want { | ||
| 150 | ++ t.Errorf("Unmarshal error mismatch\ngot: %q\nwant: %q", got, want) | ||
| 151 | ++ } | ||
| 152 | ++ }) | ||
| 153 | ++} | ||
| 154 | ++ | ||
| 155 | ++// Note that recursive structs fail in half the normal limit because each level | ||
| 156 | ++// of nesting in a struct (with a slice field) involves two depth increments | ||
| 157 | ++// (one for the struct and one for the slice). | ||
| 158 | ++func TestUnmarshalNestingLimitStruct(t *testing.T) { | ||
| 159 | ++ type Recursive struct { | ||
| 160 | ++ Next []Recursive `asn1:"optional"` | ||
| 161 | ++ } | ||
| 162 | ++ | ||
| 163 | ++ limit := 5000 | ||
| 164 | ++ if runtime.GOARCH == "wasm" { | ||
| 165 | ++ limit = 2500 | ||
| 166 | ++ } | ||
| 167 | ++ | ||
| 168 | ++ makeData := func(t *testing.T, depth int) []byte { | ||
| 169 | ++ var r Recursive | ||
| 170 | ++ for range depth - 1 { | ||
| 171 | ++ r = Recursive{Next: []Recursive{r}} | ||
| 172 | ++ } | ||
| 173 | ++ data, err := Marshal(r) | ||
| 174 | ++ if err != nil { | ||
| 175 | ++ t.Fatalf("Marshal failed: %v", err) | ||
| 176 | ++ } | ||
| 177 | ++ return data | ||
| 178 | ++ } | ||
| 179 | ++ | ||
| 180 | ++ t.Run("below limit", func(t *testing.T) { | ||
| 181 | ++ data := makeData(t, limit) | ||
| 182 | ++ var r Recursive | ||
| 183 | ++ if _, err := Unmarshal(data, &r); err != nil { | ||
| 184 | ++ t.Errorf("Unmarshal failed at depth %d: %v", limit, err) | ||
| 185 | ++ } | ||
| 186 | ++ }) | ||
| 187 | ++ | ||
| 188 | ++ t.Run("above limit", func(t *testing.T) { | ||
| 189 | ++ data := makeData(t, limit+1) | ||
| 190 | ++ var r Recursive | ||
| 191 | ++ _, err := Unmarshal(data, &r) | ||
| 192 | ++ if err == nil { | ||
| 193 | ++ t.Fatalf("Unmarshal succeeded at depth %d, want error", limit+1) | ||
| 194 | ++ } | ||
| 195 | ++ if got, want := err.Error(), "asn1: structure error: nesting depth exceeded"; got != want { | ||
| 196 | ++ t.Errorf("Unmarshal error mismatch\ngot: %q\nwant: %q", got, want) | ||
| 197 | ++ } | ||
| 198 | ++ }) | ||
| 199 | ++} | ||
| @@ -69,7 +69,7 @@ | |||
| 69 | 69 | ||
| 70 | Name: golang | 70 | Name: golang |
| 71 | Version: 1.21.4 | 71 | Version: 1.21.4 |
| 72 | -Release: 48 | 72 | +Release: 49 |
| 73 | Summary: The Go Programming Language | 73 | Summary: The Go Programming Language |
| 74 | License: BSD and Public Domain | 74 | License: BSD and Public Domain |
| 75 | URL: https://golang.org/ | 75 | URL: https://golang.org/ |
| @@ -187,6 +187,7 @@ Patch6059: backport-0059-CVE-2026-27143-cmd-compile-fix-loopbce-overflow.patch | |||
| 187 | Patch6060: backport-0060-CVE-2026-27144-cmd-compile-fix-mem-access-overlap.patch | 187 | Patch6060: backport-0060-CVE-2026-27144-cmd-compile-fix-mem-access-overlap.patch |
| 188 | Patch6061: backport-0061-CVE-2026-32288-archive-tar-limit-old-gnu-sparse.patch | 188 | Patch6061: backport-0061-CVE-2026-32288-archive-tar-limit-old-gnu-sparse.patch |
| 189 | Patch6062: backport-0062-CVE-2026-27140-cmd-go-disallow-cgo-trust-bypass.patch | 189 | Patch6062: backport-0062-CVE-2026-27140-cmd-go-disallow-cgo-trust-bypass.patch |
| 190 | +Patch6063: backport-CVE-2026-33818.patch | ||
| 190 | 191 | ||
| 191 | # Part 10001-10999 | 192 | # Part 10001-10999 |
| 192 | %ifarch sw_64 | 193 | %ifarch sw_64 |
| @@ -578,6 +579,12 @@ fi | |||
| 578 | %files devel -f go-tests.list -f go-misc.list -f go-src.list | 579 | %files devel -f go-tests.list -f go-misc.list -f go-src.list |
| 579 | 580 | ||
| 580 | %changelog | 581 | %changelog |
| 582 | +* Mon Aug 17 2026 xiaoo_robot <xiaoo_robot@petalmail.com> - 1.21.4-49 | ||
| 583 | +- Type:CVE | ||
| 584 | +- CVE:CVE-2026-33818 | ||
| 585 | +- SUG:NA | ||
| 586 | +- DESC:fix CVE-2026-33818 | ||
| 587 | + | ||
| 581 | * Wed May 06 2026 huzhangying <huzhangying@huawei.com> - 1.21.4-48 | 588 | * Wed May 06 2026 huzhangying <huzhangying@huawei.com> - 1.21.4-48 |
| 582 | - Type:CVE | 589 | - Type:CVE |
| 583 | - CVE:CVE-2026-27143,CVE-2026-27144,CVE-2026-32288,CVE-2026-27140 | 590 | - CVE:CVE-2026-27143,CVE-2026-27144,CVE-2026-32288,CVE-2026-27140 |