Skip to content

Commit 6cb5a6f

Browse files
[AUTO-CHERRYPICK] Patch docker-compose for CVE-2025-22869 & CVE-2024-10846 [High] - branch 3.0-dev (#12786)
Co-authored-by: Kanishk Bansal <[email protected]>
1 parent 51c8eb4 commit 6cb5a6f

File tree

3 files changed

+211
-1
lines changed

3 files changed

+211
-1
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
From 217663fd8fd2b7b789c9f877bbd9781d887a6b07 Mon Sep 17 00:00:00 2001
2+
From: Kanishk-Bansal <[email protected]>
3+
Date: Mon, 3 Mar 2025 04:54:06 +0000
4+
Subject: [PATCH] CVE-2024-10846
5+
Upstream Reference: https://github.com/compose-spec/compose-go/pull/703
6+
---
7+
.../compose-go/v2/loader/reset.go | 28 ++++++++++++++++---
8+
1 file changed, 24 insertions(+), 4 deletions(-)
9+
10+
diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
11+
index 2b7f04c..213d0e8 100644
12+
--- a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
13+
+++ b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
14+
@@ -26,13 +26,15 @@ import (
15+
)
16+
17+
type ResetProcessor struct {
18+
- target interface{}
19+
- paths []tree.Path
20+
+ target interface{}
21+
+ paths []tree.Path
22+
+ visitedNodes map[*yaml.Node]string
23+
}
24+
25+
// UnmarshalYAML implement yaml.Unmarshaler
26+
func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
27+
resolved, err := p.resolveReset(value, tree.NewPath())
28+
+ p.visitedNodes = nil
29+
if err != nil {
30+
return err
31+
}
32+
@@ -41,10 +43,28 @@ func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
33+
34+
// resolveReset detects `!reset` tag being set on yaml nodes and record position in the yaml tree
35+
func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.Node, error) {
36+
+ pathStr := path.String()
37+
// If the path contains "<<", removing the "<<" element and merging the path
38+
- if strings.Contains(path.String(), ".<<") {
39+
- path = tree.NewPath(strings.Replace(path.String(), ".<<", "", 1))
40+
+ if strings.Contains(pathStr, ".<<") {
41+
+ path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1))
42+
}
43+
+
44+
+ // Check for cycle
45+
+ if p.visitedNodes == nil {
46+
+ p.visitedNodes = make(map[*yaml.Node]string)
47+
+ }
48+
+
49+
+ // Check for cycle by seeing if the node has already been visited at this path
50+
+ if previousPath, found := p.visitedNodes[node]; found {
51+
+ // If the current node has been visited, we have a cycle if the previous path is a prefix
52+
+ if strings.HasPrefix(pathStr, previousPath) {
53+
+ return nil, fmt.Errorf("cycle detected at path: %s", pathStr)
54+
+ }
55+
+ }
56+
+
57+
+ // Mark the current node as visited
58+
+ p.visitedNodes[node] = pathStr
59+
+
60+
// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
61+
if node.Kind == yaml.AliasNode {
62+
return p.resolveReset(node.Alias, path)
63+
--
64+
2.45.2
65+
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
From 041b89a18f81265899e42e6801f830c101a96120 Mon Sep 17 00:00:00 2001
2+
From: Kanishk-Bansal <[email protected]>
3+
Date: Sun, 2 Mar 2025 13:46:00 +0000
4+
Subject: [PATCH] CVE-2025-22869
5+
6+
Upstream Reference : https://github.com/golang/crypto/commit/7292932d45d55c7199324ab0027cc86e8198aa22
7+
8+
ssh: limit the size of the internal packet queue while waiting for KEX
9+
10+
In the SSH protocol, clients and servers execute the key exchange to
11+
generate one-time session keys used for encryption and authentication.
12+
The key exchange is performed initially after the connection is
13+
established and then periodically after a configurable amount of data.
14+
While a key exchange is in progress, we add the received packets to an
15+
internal queue until we receive SSH_MSG_KEXINIT from the other side.
16+
This can result in high memory usage if the other party is slow to
17+
respond to the SSH_MSG_KEXINIT packet, or memory exhaustion if a
18+
malicious client never responds to an SSH_MSG_KEXINIT packet during a
19+
large file transfer.
20+
We now limit the internal queue to 64 packets: this means 2MB with the
21+
typical 32KB packet size.
22+
When the internal queue is full we block further writes until the
23+
pending key exchange is completed or there is a read or write error.
24+
25+
Thanks to Yuichi Watanabe for reporting this issue.
26+
27+
Change-Id: I1ce2214cc16e08b838d4bc346c74c72addafaeec
28+
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/652135
29+
Reviewed-by: Neal Patel <[email protected]>
30+
Auto-Submit: Gopher Robot <[email protected]>
31+
Reviewed-by: Roland Shoemaker <[email protected]>
32+
LUCI-TryBot-Result: Go LUCI <[email protected]>
33+
34+
---
35+
vendor/golang.org/x/crypto/ssh/handshake.go | 47 ++++++++++++++++-----
36+
1 file changed, 37 insertions(+), 10 deletions(-)
37+
38+
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
39+
index 70a7369..e14eb6c 100644
40+
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
41+
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
42+
@@ -24,6 +24,11 @@ const debugHandshake = false
43+
// quickly.
44+
const chanSize = 16
45+
46+
+// maxPendingPackets sets the maximum number of packets to queue while waiting
47+
+// for KEX to complete. This limits the total pending data to maxPendingPackets
48+
+// * maxPacket bytes, which is ~16.8MB.
49+
+const maxPendingPackets = 64
50+
+
51+
// keyingTransport is a packet based transport that supports key
52+
// changes. It need not be thread-safe. It should pass through
53+
// msgNewKeys in both directions.
54+
@@ -58,11 +63,19 @@ type handshakeTransport struct {
55+
incoming chan []byte
56+
readError error
57+
58+
- mu sync.Mutex
59+
- writeError error
60+
- sentInitPacket []byte
61+
- sentInitMsg *kexInitMsg
62+
- pendingPackets [][]byte // Used when a key exchange is in progress.
63+
+ mu sync.Mutex
64+
+ // Condition for the above mutex. It is used to notify a completed key
65+
+ // exchange or a write failure. Writes can wait for this condition while a
66+
+ // key exchange is in progress.
67+
+ writeCond *sync.Cond
68+
+ writeError error
69+
+ sentInitPacket []byte
70+
+ sentInitMsg *kexInitMsg
71+
+ // Used to queue writes when a key exchange is in progress. The length is
72+
+ // limited by pendingPacketsSize. Once full, writes will block until the key
73+
+ // exchange is completed or an error occurs. If not empty, it is emptied
74+
+ // all at once when the key exchange is completed in kexLoop.
75+
+ pendingPackets [][]byte
76+
writePacketsLeft uint32
77+
writeBytesLeft int64
78+
79+
@@ -114,6 +127,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
80+
81+
config: config,
82+
}
83+
+ t.writeCond = sync.NewCond(&t.mu)
84+
t.resetReadThresholds()
85+
t.resetWriteThresholds()
86+
87+
@@ -236,6 +250,7 @@ func (t *handshakeTransport) recordWriteError(err error) {
88+
defer t.mu.Unlock()
89+
if t.writeError == nil && err != nil {
90+
t.writeError = err
91+
+ t.writeCond.Broadcast()
92+
}
93+
}
94+
95+
@@ -339,6 +354,8 @@ write:
96+
}
97+
}
98+
t.pendingPackets = t.pendingPackets[:0]
99+
+ // Unblock writePacket if waiting for KEX.
100+
+ t.writeCond.Broadcast()
101+
t.mu.Unlock()
102+
}
103+
104+
@@ -526,11 +543,20 @@ func (t *handshakeTransport) writePacket(p []byte) error {
105+
}
106+
107+
if t.sentInitMsg != nil {
108+
- // Copy the packet so the writer can reuse the buffer.
109+
- cp := make([]byte, len(p))
110+
- copy(cp, p)
111+
- t.pendingPackets = append(t.pendingPackets, cp)
112+
- return nil
113+
+ if len(t.pendingPackets) < maxPendingPackets {
114+
+ // Copy the packet so the writer can reuse the buffer.
115+
+ cp := make([]byte, len(p))
116+
+ copy(cp, p)
117+
+ t.pendingPackets = append(t.pendingPackets, cp)
118+
+ return nil
119+
+ }
120+
+ for t.sentInitMsg != nil {
121+
+ // Block and wait for KEX to complete or an error.
122+
+ t.writeCond.Wait()
123+
+ if t.writeError != nil {
124+
+ return t.writeError
125+
+ }
126+
+ }
127+
}
128+
129+
if t.writeBytesLeft > 0 {
130+
@@ -547,6 +573,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {
131+
132+
if err := t.pushPacket(p); err != nil {
133+
t.writeError = err
134+
+ t.writeCond.Broadcast()
135+
}
136+
137+
return nil
138+
--
139+
2.45.2
140+

SPECS/docker-compose/docker-compose.spec

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Summary: Define and run multi-container applications with Docker
22
Name: docker-compose
33
Version: 2.27.0
4-
Release: 3%{?dist}
4+
Release: 4%{?dist}
55
License: ASL 2.0
66
Vendor: Microsoft Corporation
77
Distribution: Azure Linux
@@ -14,6 +14,8 @@ Source0: https://github.com/docker/compose/archive/refs/tags/v%{version}.
1414
Source1: %{name}-%{version}-govendor-v1.tar.gz
1515
Patch0: CVE-2024-45337.patch
1616
Patch1: CVE-2024-45338.patch
17+
Patch2: CVE-2025-22869.patch
18+
Patch3: CVE-2024-10846.patch
1719
BuildRequires: golang
1820
Requires: docker-cli
1921
Obsoletes: moby-compose < %{version}-%{release}
@@ -46,6 +48,9 @@ install -D -m0755 bin/build/docker-compose %{buildroot}/%{_libexecdir}/docker/cl
4648
%{_libexecdir}/docker/cli-plugins/docker-compose
4749

4850
%changelog
51+
* Mon Mar 03 2025 Kanishk Bansal <[email protected]> - 2.27.0-4
52+
- Fix CVE-2025-22869, CVE-2024-10846 with an upstream patch
53+
4954
* Tue Dec 31 2024 Rohit Rawat <[email protected]> - 2.27.0-3
5055
- Add patch for CVE-2024-45338
5156

0 commit comments

Comments
 (0)