diff mbox series

[kirkstone,1/1] go: Fix CVE-2024-34158

Message ID 20250108055421.3341813-3-archana.polampalli@windriver.com
State New
Headers show
Series [kirkstone,1/1] go: Fix CVE-2024-34158 | expand

Commit Message

Polampalli, Archana Jan. 8, 2025, 5:54 a.m. UTC
From: Archana Polampalli <archana.polampalli@windriver.com>

Calling Parse on a "// +build" build tag line with deeply nested
expressions can cause a panic due to stack exhaustion.

Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-34158

Upstream-patch:
https://github.com/golang/go/commit/d4c53812e6ce2ac368173d7fcd31d0ecfcffb002

Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
---
 meta/recipes-devtools/go/go-1.17.13.inc       |   1 +
 .../go/go-1.21/CVE-2024-34158.patch           | 205 ++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 meta/recipes-devtools/go/go-1.21/CVE-2024-34158.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
index 53ca869221..c483590931 100644
--- a/meta/recipes-devtools/go/go-1.17.13.inc
+++ b/meta/recipes-devtools/go/go-1.17.13.inc
@@ -60,6 +60,7 @@  SRC_URI += "\
     file://CVE-2024-24791.patch \
     file://CVE-2024-34155.patch \
     file://CVE-2024-34156.patch \
+    file://CVE-2024-34158.patch \
 "
 SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
 
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2024-34158.patch b/meta/recipes-devtools/go/go-1.21/CVE-2024-34158.patch
new file mode 100644
index 0000000000..ad4d4f092c
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.21/CVE-2024-34158.patch
@@ -0,0 +1,205 @@ 
+From d4c53812e6ce2ac368173d7fcd31d0ecfcffb002 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Thu, 20 Jun 2024 10:45:30 -0700
+Subject: [PATCH] go/build/constraint: add parsing limits
+
+Limit the size of build constraints that we will parse. This prevents a
+number of stack exhaustions that can be hit when parsing overly complex
+constraints. The imposed limits are unlikely to ever be hit in real
+world usage.
+
+Updates #69141
+Fixes #69148
+Fixes CVE-2024-34158
+
+Change-Id: I38b614bf04caa36eefc6a4350d848588c4cef3c4
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1540
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Russ Cox <rsc@google.com>
+(cherry picked from commit 0c74dc9e0da0cf1e12494b514d822b5bebbc9f04)
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1582
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/611183
+Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Michael Pratt <mpratt@google.com>
+TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
+
+CVE: CVE-2024-34158
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/d4c53812e6ce2ac368173d7fcd31d0ecfcffb002]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ src/go/build/constraint/expr.go      | 28 ++++++++++--
+ src/go/build/constraint/expr_test.go | 65 +++++++++++++++++++++++++++-
+ 2 files changed, 89 insertions(+), 4 deletions(-)
+
+diff --git a/src/go/build/constraint/expr.go b/src/go/build/constraint/expr.go
+index 957eb9b..85897e2 100644
+--- a/src/go/build/constraint/expr.go
++++ b/src/go/build/constraint/expr.go
+@@ -18,6 +18,10 @@ import (
+	"unicode/utf8"
+ )
+
++// maxSize is a limit used to control the complexity of expressions, in order
++// to prevent stack exhaustion issues due to recursion.
++const maxSize = 1000
++
+ // An Expr is a build tag constraint expression.
+ // The underlying concrete type is *AndExpr, *OrExpr, *NotExpr, or *TagExpr.
+ type Expr interface {
+@@ -153,7 +157,7 @@ func Parse(line string) (Expr, error) {
+		return parseExpr(text)
+	}
+	if text, ok := splitPlusBuild(line); ok {
+-		return parsePlusBuildExpr(text), nil
++		return parsePlusBuildExpr(text)
+	}
+	return nil, errNotConstraint
+ }
+@@ -203,6 +207,8 @@ type exprParser struct {
+	tok   string // last token read
+	isTag bool
+	pos   int // position (start) of last token
++
++	size int
+ }
+
+ // parseExpr parses a boolean build tag expression.
+@@ -251,6 +257,10 @@ func (p *exprParser) and() Expr {
+ // On entry, the next input token has not yet been lexed.
+ // On exit, the next input token has been lexed and is in p.tok.
+ func (p *exprParser) not() Expr {
++	p.size++
++	if p.size > maxSize {
++		panic(&SyntaxError{Offset: p.pos, Err: "build expression too large"})
++	}
+	p.lex()
+	if p.tok == "!" {
+		p.lex()
+@@ -391,7 +401,13 @@ func splitPlusBuild(line string) (expr string, ok bool) {
+ }
+
+ // parsePlusBuildExpr parses a legacy build tag expression (as used with “// +build”).
+-func parsePlusBuildExpr(text string) Expr {
++func parsePlusBuildExpr(text string) (Expr, error) {
++	// Only allow up to 100 AND/OR operators for "old" syntax.
++	// This is much less than the limit for "new" syntax,
++	// but uses of old syntax were always very simple.
++	const maxOldSize = 100
++	size := 0
++
+	var x Expr
+	for _, clause := range strings.Fields(text) {
+		var y Expr
+@@ -417,19 +433,25 @@ func parsePlusBuildExpr(text string) Expr {
+			if y == nil {
+				y = z
+			} else {
++				if size++; size > maxOldSize {
++					return nil, errComplex
++				}
+				y = and(y, z)
+			}
+		}
+		if x == nil {
+			x = y
+		} else {
++			if size++; size > maxOldSize {
++				return nil, errComplex
++			}
+			x = or(x, y)
+		}
+	}
+	if x == nil {
+		x = tag("ignore")
+	}
+-	return x
++	return x, nil
+ }
+
+ // isValidTag reports whether the word is a valid build tag.
+diff --git a/src/go/build/constraint/expr_test.go b/src/go/build/constraint/expr_test.go
+index 15d1890..ac38ba6 100644
+--- a/src/go/build/constraint/expr_test.go
++++ b/src/go/build/constraint/expr_test.go
+@@ -222,7 +222,7 @@ var parsePlusBuildExprTests = []struct {
+ func TestParsePlusBuildExpr(t *testing.T) {
+	for i, tt := range parsePlusBuildExprTests {
+		t.Run(fmt.Sprint(i), func(t *testing.T) {
+-			x := parsePlusBuildExpr(tt.in)
++			x, _ := parsePlusBuildExpr(tt.in)
+			if x.String() != tt.x.String() {
+				t.Errorf("parsePlusBuildExpr(%q):\nhave %v\nwant %v", tt.in, x, tt.x)
+			}
+@@ -319,3 +319,66 @@ func TestPlusBuildLines(t *testing.T) {
+		})
+	}
+ }
++
++func TestSizeLimits(t *testing.T) {
++	for _, tc := range []struct {
++		name string
++		expr string
++	}{
++		{
++			name: "go:build or limit",
++			expr: "//go:build " + strings.Repeat("a || ", maxSize+2),
++		},
++		{
++			name: "go:build and limit",
++			expr: "//go:build " + strings.Repeat("a && ", maxSize+2),
++		},
++		{
++			name: "go:build and depth limit",
++			expr: "//go:build " + strings.Repeat("(a &&", maxSize+2),
++		},
++		{
++			name: "go:build or depth limit",
++			expr: "//go:build " + strings.Repeat("(a ||", maxSize+2),
++		},
++	} {
++		t.Run(tc.name, func(t *testing.T) {
++			_, err := Parse(tc.expr)
++			if err == nil {
++				t.Error("expression did not trigger limit")
++			} else if syntaxErr, ok := err.(*SyntaxError); !ok || syntaxErr.Err != "build expression too large" {
++				if !ok {
++					t.Errorf("unexpected error: %v", err)
++				} else {
++					t.Errorf("unexpected syntax error: %s", syntaxErr.Err)
++				}
++			}
++		})
++	}
++}
++
++func TestPlusSizeLimits(t *testing.T) {
++	maxOldSize := 100
++	for _, tc := range []struct {
++		name string
++		expr string
++	}{
++		{
++			name: "+build or limit",
++			expr: "// +build " + strings.Repeat("a ", maxOldSize+2),
++		},
++		{
++			name: "+build and limit",
++			expr: "// +build " + strings.Repeat("a,", maxOldSize+2),
++		},
++	} {
++		t.Run(tc.name, func(t *testing.T) {
++			_, err := Parse(tc.expr)
++			if err == nil {
++				t.Error("expression did not trigger limit")
++			} else if err != errComplex {
++				t.Errorf("unexpected error: got %q, want %q", err, errComplex)
++			}
++		})
++	}
++}
+--
+2.40.0