diff options
| author | Vijay Anusuri <vanusuri@mvista.com> | 2025-12-29 18:17:54 +0530 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2026-01-02 07:21:42 -0800 |
| commit | 690dcd26216a6a2e8994592fb7ad56395c5ddf36 (patch) | |
| tree | 30663ce84d334097d375dcc05d77635147c82b84 | |
| parent | 084488d13fe957c146c3cb75c286419409a6f451 (diff) | |
| download | poky-690dcd26216a6a2e8994592fb7ad56395c5ddf36.tar.gz | |
go: Fix CVE-2025-61727
Upstream-Status: Backport from https://github.com/golang/go/commit/04db77a423cac75bb82cc9a6859991ae9c016344
(From OE-Core rev: dc1d95e3edfeaa5458fc564910ae5c9445a6f942)
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
| -rw-r--r-- | meta/recipes-devtools/go/go-1.17.13.inc | 1 | ||||
| -rw-r--r-- | meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch | 229 |
2 files changed, 230 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc index 1433d54f06..0ea3b6704f 100644 --- a/meta/recipes-devtools/go/go-1.17.13.inc +++ b/meta/recipes-devtools/go/go-1.17.13.inc | |||
| @@ -75,6 +75,7 @@ SRC_URI = "https://golang.org/dl/go${PV}.src.tar.gz;name=main \ | |||
| 75 | file://CVE-2025-61723.patch \ | 75 | file://CVE-2025-61723.patch \ |
| 76 | file://CVE-2025-61724.patch \ | 76 | file://CVE-2025-61724.patch \ |
| 77 | file://CVE-2023-39323.patch \ | 77 | file://CVE-2023-39323.patch \ |
| 78 | file://CVE-2025-61727.patch \ | ||
| 78 | " | 79 | " |
| 79 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" | 80 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" |
| 80 | 81 | ||
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch new file mode 100644 index 0000000000..23dc35b8b8 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | From 04db77a423cac75bb82cc9a6859991ae9c016344 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Roland Shoemaker <bracewell@google.com> | ||
| 3 | Date: Mon, 24 Nov 2025 08:46:08 -0800 | ||
| 4 | Subject: [PATCH] [release-branch.go1.24] crypto/x509: excluded subdomain | ||
| 5 | constraints preclude wildcard SANs | ||
| 6 | |||
| 7 | When evaluating name constraints in a certificate chain, the presence of | ||
| 8 | an excluded subdomain constraint (e.g., excluding "test.example.com") | ||
| 9 | should preclude the use of a wildcard SAN (e.g., "*.example.com"). | ||
| 10 | |||
| 11 | Fixes #76442 | ||
| 12 | Fixes #76463 | ||
| 13 | Fixes CVE-2025-61727 | ||
| 14 | |||
| 15 | Change-Id: I42a0da010cb36d2ec9d1239ae3f61cf25eb78bba | ||
| 16 | Reviewed-on: https://go-review.googlesource.com/c/go/+/724401 | ||
| 17 | Reviewed-by: Nicholas Husin <husin@google.com> | ||
| 18 | Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> | ||
| 19 | LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> | ||
| 20 | Reviewed-by: Nicholas Husin <nsh@golang.org> | ||
| 21 | Reviewed-by: Neal Patel <nealpatel@google.com> | ||
| 22 | |||
| 23 | Upstream-Status: Backport [https://github.com/golang/go/commit/04db77a423cac75bb82cc9a6859991ae9c016344] | ||
| 24 | CVE: CVE-2025-61727 | ||
| 25 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 26 | --- | ||
| 27 | src/crypto/x509/name_constraints_test.go | 34 ++++++++++++++++++++ | ||
| 28 | src/crypto/x509/verify.go | 40 +++++++++++++++--------- | ||
| 29 | src/crypto/x509/verify_test.go | 2 +- | ||
| 30 | 3 files changed, 60 insertions(+), 16 deletions(-) | ||
| 31 | |||
| 32 | diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go | ||
| 33 | index c59a7dc..963bc5a 100644 | ||
| 34 | --- a/src/crypto/x509/name_constraints_test.go | ||
| 35 | +++ b/src/crypto/x509/name_constraints_test.go | ||
| 36 | @@ -1595,6 +1595,40 @@ var nameConstraintsTests = []nameConstraintsTest{ | ||
| 37 | cn: "foo.bar", | ||
| 38 | }, | ||
| 39 | }, | ||
| 40 | + // #87: subdomain excluded constraints preclude wildcard names | ||
| 41 | + { | ||
| 42 | + roots: []constraintsSpec{ | ||
| 43 | + { | ||
| 44 | + bad: []string{"dns:foo.example.com"}, | ||
| 45 | + }, | ||
| 46 | + }, | ||
| 47 | + intermediates: [][]constraintsSpec{ | ||
| 48 | + { | ||
| 49 | + {}, | ||
| 50 | + }, | ||
| 51 | + }, | ||
| 52 | + leaf: leafSpec{ | ||
| 53 | + sans: []string{"dns:*.example.com"}, | ||
| 54 | + }, | ||
| 55 | + expectedError: "\"*.example.com\" is excluded by constraint \"foo.example.com\"", | ||
| 56 | + }, | ||
| 57 | + // #88: wildcard names are not matched by subdomain permitted constraints | ||
| 58 | + { | ||
| 59 | + roots: []constraintsSpec{ | ||
| 60 | + { | ||
| 61 | + ok: []string{"dns:foo.example.com"}, | ||
| 62 | + }, | ||
| 63 | + }, | ||
| 64 | + intermediates: [][]constraintsSpec{ | ||
| 65 | + { | ||
| 66 | + {}, | ||
| 67 | + }, | ||
| 68 | + }, | ||
| 69 | + leaf: leafSpec{ | ||
| 70 | + sans: []string{"dns:*.example.com"}, | ||
| 71 | + }, | ||
| 72 | + expectedError: "\"*.example.com\" is not permitted", | ||
| 73 | + }, | ||
| 74 | } | ||
| 75 | |||
| 76 | func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { | ||
| 77 | diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go | ||
| 78 | index 99f38a0..88260ee 100644 | ||
| 79 | --- a/src/crypto/x509/verify.go | ||
| 80 | +++ b/src/crypto/x509/verify.go | ||
| 81 | @@ -390,7 +390,7 @@ func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { | ||
| 82 | return reverseLabels, true | ||
| 83 | } | ||
| 84 | |||
| 85 | -func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 86 | +func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 87 | // If the constraint contains an @, then it specifies an exact mailbox | ||
| 88 | // name. | ||
| 89 | if strings.Contains(constraint, "@") { | ||
| 90 | @@ -403,10 +403,10 @@ func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDom | ||
| 91 | |||
| 92 | // Otherwise the constraint is like a DNS constraint of the domain part | ||
| 93 | // of the mailbox. | ||
| 94 | - return matchDomainConstraint(mailbox.domain, constraint, reversedDomainsCache, reversedConstraintsCache) | ||
| 95 | + return matchDomainConstraint(mailbox.domain, constraint, excluded, reversedDomainsCache, reversedConstraintsCache) | ||
| 96 | } | ||
| 97 | |||
| 98 | -func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 99 | +func matchURIConstraint(uri *url.URL, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 100 | // From RFC 5280, Section 4.2.1.10: | ||
| 101 | // “a uniformResourceIdentifier that does not include an authority | ||
| 102 | // component with a host name specified as a fully qualified domain | ||
| 103 | @@ -433,7 +433,7 @@ func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache ma | ||
| 104 | return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) | ||
| 105 | } | ||
| 106 | |||
| 107 | - return matchDomainConstraint(host, constraint, reversedDomainsCache, reversedConstraintsCache) | ||
| 108 | + return matchDomainConstraint(host, constraint, excluded, reversedDomainsCache, reversedConstraintsCache) | ||
| 109 | } | ||
| 110 | |||
| 111 | func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) { | ||
| 112 | @@ -450,7 +450,7 @@ func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) { | ||
| 113 | return true, nil | ||
| 114 | } | ||
| 115 | |||
| 116 | -func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 117 | +func matchDomainConstraint(domain, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) { | ||
| 118 | // The meaning of zero length constraints is not specified, but this | ||
| 119 | // code follows NSS and accepts them as matching everything. | ||
| 120 | if len(constraint) == 0 { | ||
| 121 | @@ -467,6 +467,11 @@ func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[s | ||
| 122 | reversedDomainsCache[domain] = domainLabels | ||
| 123 | } | ||
| 124 | |||
| 125 | + wildcardDomain := false | ||
| 126 | + if len(domain) > 0 && domain[0] == '*' { | ||
| 127 | + wildcardDomain = true | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | // RFC 5280 says that a leading period in a domain name means that at | ||
| 131 | // least one label must be prepended, but only for URI and email | ||
| 132 | // constraints, not DNS constraints. The code also supports that | ||
| 133 | @@ -493,6 +498,11 @@ func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[s | ||
| 134 | return false, nil | ||
| 135 | } | ||
| 136 | |||
| 137 | + if excluded && wildcardDomain && len(domainLabels) > 1 && len(constraintLabels) > 0 { | ||
| 138 | + domainLabels = domainLabels[:len(domainLabels)-1] | ||
| 139 | + constraintLabels = constraintLabels[:len(constraintLabels)-1] | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | for i, constraintLabel := range constraintLabels { | ||
| 143 | if !strings.EqualFold(constraintLabel, domainLabels[i]) { | ||
| 144 | return false, nil | ||
| 145 | @@ -512,7 +522,7 @@ func (c *Certificate) checkNameConstraints(count *int, | ||
| 146 | nameType string, | ||
| 147 | name string, | ||
| 148 | parsedName interface{}, | ||
| 149 | - match func(parsedName, constraint interface{}) (match bool, err error), | ||
| 150 | + match func(parsedName, constraint interface{}, excluded bool) (match bool, err error), | ||
| 151 | permitted, excluded interface{}) error { | ||
| 152 | |||
| 153 | excludedValue := reflect.ValueOf(excluded) | ||
| 154 | @@ -524,7 +534,7 @@ func (c *Certificate) checkNameConstraints(count *int, | ||
| 155 | |||
| 156 | for i := 0; i < excludedValue.Len(); i++ { | ||
| 157 | constraint := excludedValue.Index(i).Interface() | ||
| 158 | - match, err := match(parsedName, constraint) | ||
| 159 | + match, err := match(parsedName, constraint, true) | ||
| 160 | if err != nil { | ||
| 161 | return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} | ||
| 162 | } | ||
| 163 | @@ -546,7 +556,7 @@ func (c *Certificate) checkNameConstraints(count *int, | ||
| 164 | constraint := permittedValue.Index(i).Interface() | ||
| 165 | |||
| 166 | var err error | ||
| 167 | - if ok, err = match(parsedName, constraint); err != nil { | ||
| 168 | + if ok, err = match(parsedName, constraint, false); err != nil { | ||
| 169 | return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} | ||
| 170 | } | ||
| 171 | |||
| 172 | @@ -633,8 +643,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V | ||
| 173 | } | ||
| 174 | |||
| 175 | if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, | ||
| 176 | - func(parsedName, constraint interface{}) (bool, error) { | ||
| 177 | - return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), reversedDomainsCache, reversedConstraintsCache) | ||
| 178 | + func(parsedName, constraint interface{}, excluded bool) (bool, error) { | ||
| 179 | + return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache) | ||
| 180 | }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { | ||
| 181 | return err | ||
| 182 | } | ||
| 183 | @@ -646,8 +656,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V | ||
| 184 | } | ||
| 185 | |||
| 186 | if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, | ||
| 187 | - func(parsedName, constraint interface{}) (bool, error) { | ||
| 188 | - return matchDomainConstraint(parsedName.(string), constraint.(string), reversedDomainsCache, reversedConstraintsCache) | ||
| 189 | + func(parsedName, constraint interface{}, excluded bool) (bool, error) { | ||
| 190 | + return matchDomainConstraint(parsedName.(string), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache) | ||
| 191 | }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { | ||
| 192 | return err | ||
| 193 | } | ||
| 194 | @@ -660,8 +670,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V | ||
| 195 | } | ||
| 196 | |||
| 197 | if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, | ||
| 198 | - func(parsedName, constraint interface{}) (bool, error) { | ||
| 199 | - return matchURIConstraint(parsedName.(*url.URL), constraint.(string), reversedDomainsCache, reversedConstraintsCache) | ||
| 200 | + func(parsedName, constraint interface{}, excluded bool) (bool, error) { | ||
| 201 | + return matchURIConstraint(parsedName.(*url.URL), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache) | ||
| 202 | }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { | ||
| 203 | return err | ||
| 204 | } | ||
| 205 | @@ -673,7 +683,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V | ||
| 206 | } | ||
| 207 | |||
| 208 | if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, | ||
| 209 | - func(parsedName, constraint interface{}) (bool, error) { | ||
| 210 | + func(parsedName, constraint interface{}, _ bool) (bool, error) { | ||
| 211 | return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) | ||
| 212 | }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { | ||
| 213 | return err | ||
| 214 | diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go | ||
| 215 | index 31e8149..5f7c834 100644 | ||
| 216 | --- a/src/crypto/x509/verify_test.go | ||
| 217 | +++ b/src/crypto/x509/verify_test.go | ||
| 218 | @@ -1648,7 +1648,7 @@ var nameConstraintTests = []struct { | ||
| 219 | |||
| 220 | func TestNameConstraints(t *testing.T) { | ||
| 221 | for i, test := range nameConstraintTests { | ||
| 222 | - result, err := matchDomainConstraint(test.domain, test.constraint, map[string][]string{}, map[string][]string{}) | ||
| 223 | + result, err := matchDomainConstraint(test.domain, test.constraint, false, map[string][]string{}, map[string][]string{}) | ||
| 224 | |||
| 225 | if err != nil && !test.expectError { | ||
| 226 | t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err) | ||
| 227 | -- | ||
| 228 | 2.25.1 | ||
| 229 | |||
