summaryrefslogtreecommitdiffstats
path: root/meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch
diff options
context:
space:
mode:
authorSoumya Sambu <soumya.sambu@windriver.com>2025-04-23 04:59:35 +0000
committerArmin Kuster <akuster808@gmail.com>2025-05-25 14:48:44 -0400
commit5c4b61d38a86de2c26f4ce5e57aaa169643ac211 (patch)
tree3ce31e28cf34dcf1ddf5dddd3ec9869acd05843d /meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch
parent85275437cd64196d1bef8e16656df04201296fbf (diff)
downloadmeta-openembedded-5c4b61d38a86de2c26f4ce5e57aaa169643ac211.tar.gz
python3-twisted: Fix CVE-2024-41671
Twisted is an event-based framework for internet applications, supporting Python 3.6+. The HTTP 1.0 and 1.1 server provided by twisted.web could process pipelined HTTP requests out-of-order, possibly resulting in information disclosure. This vulnerability is fixed in 24.7.0rc1. References: https://nvd.nist.gov/vuln/detail/CVE-2024-41671 https://ubuntu.com/security/CVE-2024-41671 Upstream patches: https://github.com/twisted/twisted/commit/f1cb4e616e9f23b4dd044a6db44365060950c64f https://github.com/twisted/twisted/commit/ef2c755e9e9d57d58132af790bd2fd2b957b3fb1 Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
Diffstat (limited to 'meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch')
-rw-r--r--meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch196
1 files changed, 196 insertions, 0 deletions
diff --git a/meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch b/meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch
new file mode 100644
index 0000000000..4775f1c55c
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-twisted/CVE-2024-41671-0002.patch
@@ -0,0 +1,196 @@
1From ef2c755e9e9d57d58132af790bd2fd2b957b3fb1 Mon Sep 17 00:00:00 2001
2From: Tom Most <twm@freecog.net>
3Date: Mon, 22 Jul 2024 23:21:49 -0700
4Subject: [PATCH] Tests and partial fix
5
6CVE: CVE-2024-41671
7
8Upstream-Status: Backport [https://github.com/twisted/twisted/commit/ef2c755e9e9d57d58132af790bd2fd2b957b3fb1]
9
10Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
11---
12 src/twisted/web/http.py | 2 +-
13 src/twisted/web/test/test_http.py | 112 +++++++++++++++++++++++++++---
14 2 files changed, 102 insertions(+), 12 deletions(-)
15
16diff --git a/src/twisted/web/http.py b/src/twisted/web/http.py
17index a53ebc2..96a1335 100644
18--- a/src/twisted/web/http.py
19+++ b/src/twisted/web/http.py
20@@ -2256,8 +2256,8 @@ class HTTPChannel(basic.LineReceiver, policies.TimeoutMixin):
21 self.__header = line
22
23 def _finishRequestBody(self, data):
24- self.allContentReceived()
25 self._dataBuffer.append(data)
26+ self.allContentReceived()
27
28 def _maybeChooseTransferDecoder(self, header, data):
29 """
30diff --git a/src/twisted/web/test/test_http.py b/src/twisted/web/test/test_http.py
31index 5d88ff1..86c85d2 100644
32--- a/src/twisted/web/test/test_http.py
33+++ b/src/twisted/web/test/test_http.py
34@@ -136,7 +136,7 @@ class DummyHTTPHandler(http.Request):
35 data = self.content.read()
36 length = self.getHeader(b"content-length")
37 if length is None:
38- length = networkString(str(length))
39+ length = str(length).encode()
40 request = b"'''\n" + length + b"\n" + data + b"'''\n"
41 self.setResponseCode(200)
42 self.setHeader(b"Request", self.uri)
43@@ -567,7 +567,8 @@ class HTTP0_9Tests(HTTP1_0Tests):
44
45 class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
46 """
47- Tests that multiple pipelined requests with bodies are correctly buffered.
48+ Pipelined requests get buffered and executed in the order received,
49+ not processed in parallel.
50 """
51
52 requests = (
53@@ -578,8 +579,9 @@ class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
54 b"Transfer-Encoding: chunked\r\n"
55 b"\r\n"
56 b"a\r\n"
57- b"0123456789"
58+ b"0123456789\r\n"
59 b"0\r\n"
60+ b"\r\n"
61 )
62
63 expectedResponses = [
64@@ -596,14 +598,16 @@ class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
65 b"Request: /",
66 b"Command: POST",
67 b"Version: HTTP/1.1",
68- b"Content-Length: 21",
69- b"'''\n10\n0123456789'''\n",
70+ b"Content-Length: 23",
71+ b"'''\nNone\n0123456789'''\n",
72 ),
73 ]
74
75- def test_noPipelining(self):
76+ def test_stepwiseTinyTube(self):
77 """
78- Test that pipelined requests get buffered, not processed in parallel.
79+ Imitate a slow connection that delivers one byte at a time.
80+ The request handler (L{DelayedHTTPHandler}) is puppeted to
81+ step through the handling of each request.
82 """
83 b = StringTransport()
84 a = http.HTTPChannel()
85@@ -612,10 +616,9 @@ class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
86 # one byte at a time, to stress it.
87 for byte in iterbytes(self.requests):
88 a.dataReceived(byte)
89- value = b.value()
90
91 # So far only one request should have been dispatched.
92- self.assertEqual(value, b"")
93+ self.assertEqual(b.value(), b"")
94 self.assertEqual(1, len(a.requests))
95
96 # Now, process each request one at a time.
97@@ -624,8 +627,95 @@ class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
98 request = a.requests[0].original
99 request.delayedProcess()
100
101- value = b.value()
102- self.assertResponseEquals(value, self.expectedResponses)
103+ self.assertResponseEquals(b.value(), self.expectedResponses)
104+
105+ def test_stepwiseDumpTruck(self):
106+ """
107+ Imitate a fast connection where several pipelined
108+ requests arrive in a single read. The request handler
109+ (L{DelayedHTTPHandler}) is puppeted to step through the
110+ handling of each request.
111+ """
112+ b = StringTransport()
113+ a = http.HTTPChannel()
114+ a.requestFactory = DelayedHTTPHandlerProxy
115+ a.makeConnection(b)
116+
117+ a.dataReceived(self.requests)
118+
119+ # So far only one request should have been dispatched.
120+ self.assertEqual(b.value(), b"")
121+ self.assertEqual(1, len(a.requests))
122+
123+ # Now, process each request one at a time.
124+ while a.requests:
125+ self.assertEqual(1, len(a.requests))
126+ request = a.requests[0].original
127+ request.delayedProcess()
128+
129+ self.assertResponseEquals(b.value(), self.expectedResponses)
130+
131+ def test_immediateTinyTube(self):
132+ """
133+ Imitate a slow connection that delivers one byte at a time.
134+
135+ (L{DummyHTTPHandler}) immediately responds, but no more
136+ than one
137+ """
138+ b = StringTransport()
139+ a = http.HTTPChannel()
140+ a.requestFactory = DummyHTTPHandlerProxy # "sync"
141+ a.makeConnection(b)
142+
143+ # one byte at a time, to stress it.
144+ for byte in iterbytes(self.requests):
145+ a.dataReceived(byte)
146+ # There is never more than one request dispatched at a time:
147+ self.assertLessEqual(len(a.requests), 1)
148+
149+ self.assertResponseEquals(b.value(), self.expectedResponses)
150+
151+ def test_immediateDumpTruck(self):
152+ """
153+ Imitate a fast connection where several pipelined
154+ requests arrive in a single read. The request handler
155+ (L{DummyHTTPHandler}) immediately responds.
156+
157+ This doesn't check the at-most-one pending request
158+ invariant but exercises otherwise uncovered code paths.
159+ See GHSA-c8m8-j448-xjx7.
160+ """
161+ b = StringTransport()
162+ a = http.HTTPChannel()
163+ a.requestFactory = DummyHTTPHandlerProxy
164+ a.makeConnection(b)
165+
166+ # All bytes at once to ensure there's stuff to buffer.
167+ a.dataReceived(self.requests)
168+
169+ self.assertResponseEquals(b.value(), self.expectedResponses)
170+
171+ def test_immediateABiggerTruck(self):
172+ """
173+ Imitate a fast connection where a so many pipelined
174+ requests arrive in a single read that backpressure is indicated.
175+ The request handler (L{DummyHTTPHandler}) immediately responds.
176+
177+ This doesn't check the at-most-one pending request
178+ invariant but exercises otherwise uncovered code paths.
179+ See GHSA-c8m8-j448-xjx7.
180+
181+ @see: L{http.HTTPChannel._optimisticEagerReadSize}
182+ """
183+ b = StringTransport()
184+ a = http.HTTPChannel()
185+ a.requestFactory = DummyHTTPHandlerProxy
186+ a.makeConnection(b)
187+
188+ overLimitCount = a._optimisticEagerReadSize // len(self.requests) * 10
189+ a.dataReceived(self.requests * overLimitCount)
190+
191+ self.assertResponseEquals(b.value(), self.expectedResponses * overLimitCount)
192
193 def test_pipeliningReadLimit(self):
194 """
195--
1962.40.0