diff options
Diffstat (limited to 'meta-python/recipes-devtools/python/python3-waitress/CVE-2024-49768-2.patch')
| -rw-r--r-- | meta-python/recipes-devtools/python/python3-waitress/CVE-2024-49768-2.patch | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/meta-python/recipes-devtools/python/python3-waitress/CVE-2024-49768-2.patch b/meta-python/recipes-devtools/python/python3-waitress/CVE-2024-49768-2.patch new file mode 100644 index 0000000000..88d6aba0e2 --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-waitress/CVE-2024-49768-2.patch | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | From 7f40812194ebbf189692f530422204b41204eecb Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Delta Regeer <bertjw@regeer.org> | ||
| 3 | Date: Sat, 26 Oct 2024 22:12:14 -0600 | ||
| 4 | Subject: [PATCH] Add a new test to validate the lookahead race condition | ||
| 5 | |||
| 6 | CVE: CVE-2024-49768 | ||
| 7 | Upstream-Status: Backport [https://github.com/Pylons/waitress/commit/6943dcf556610ece2ff3cddb39e59a05ef110661] | ||
| 8 | Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> | ||
| 9 | --- | ||
| 10 | tests/test_channel.py | 55 ++++++++++++++++++++++++++++++++++++++++++- | ||
| 11 | 1 file changed, 54 insertions(+), 1 deletion(-) | ||
| 12 | |||
| 13 | diff --git a/tests/test_channel.py b/tests/test_channel.py | ||
| 14 | index 7d677e9..d798091 100644 | ||
| 15 | --- a/tests/test_channel.py | ||
| 16 | +++ b/tests/test_channel.py | ||
| 17 | @@ -805,11 +805,12 @@ class TestHTTPChannelLookahead(TestHTTPChannel): | ||
| 18 | ) | ||
| 19 | return [body] | ||
| 20 | |||
| 21 | - def _make_app_with_lookahead(self): | ||
| 22 | + def _make_app_with_lookahead(self, recv_bytes=8192): | ||
| 23 | """ | ||
| 24 | Setup a channel with lookahead and store it and the socket in self | ||
| 25 | """ | ||
| 26 | adj = DummyAdjustments() | ||
| 27 | + adj.recv_bytes = recv_bytes | ||
| 28 | adj.channel_request_lookahead = 5 | ||
| 29 | channel, sock, map = self._makeOneWithMap(adj=adj) | ||
| 30 | channel.server.application = self.app_check_disconnect | ||
| 31 | @@ -901,6 +902,58 @@ class TestHTTPChannelLookahead(TestHTTPChannel): | ||
| 32 | self.assertEqual(data.split("\r\n")[-1], "finished") | ||
| 33 | self.assertEqual(self.request_body, b"x") | ||
| 34 | |||
| 35 | + def test_lookahead_bad_request_drop_extra_data(self): | ||
| 36 | + """ | ||
| 37 | + Send two requests, the first one being bad, split on the recv_bytes | ||
| 38 | + limit, then emulate a race that could happen whereby we read data from | ||
| 39 | + the socket while the service thread is cleaning up due to an error | ||
| 40 | + processing the request. | ||
| 41 | + """ | ||
| 42 | + | ||
| 43 | + invalid_request = [ | ||
| 44 | + "GET / HTTP/1.1", | ||
| 45 | + "Host: localhost:8080", | ||
| 46 | + "Content-length: -1", | ||
| 47 | + "", | ||
| 48 | + ] | ||
| 49 | + | ||
| 50 | + invalid_request_len = len("".join([x + "\r\n" for x in invalid_request])) | ||
| 51 | + | ||
| 52 | + second_request = [ | ||
| 53 | + "POST / HTTP/1.1", | ||
| 54 | + "Host: localhost:8080", | ||
| 55 | + "Content-Length: 1", | ||
| 56 | + "", | ||
| 57 | + "x", | ||
| 58 | + ] | ||
| 59 | + | ||
| 60 | + full_request = invalid_request + second_request | ||
| 61 | + | ||
| 62 | + self._make_app_with_lookahead(recv_bytes=invalid_request_len) | ||
| 63 | + self._send(*full_request) | ||
| 64 | + self.channel.handle_read() | ||
| 65 | + self.assertEqual(len(self.channel.requests), 1) | ||
| 66 | + self.channel.server.tasks[0].service() | ||
| 67 | + self.assertTrue(self.channel.close_when_flushed) | ||
| 68 | + # Read all of the next request | ||
| 69 | + self.channel.handle_read() | ||
| 70 | + self.channel.handle_read() | ||
| 71 | + # Validate that there is no more data to be read | ||
| 72 | + self.assertEqual(self.sock.remote.local_sent, b"") | ||
| 73 | + # Validate that we dropped the data from the second read, and did not | ||
| 74 | + # create a new request | ||
| 75 | + self.assertEqual(len(self.channel.requests), 0) | ||
| 76 | + data = self.sock.recv(256).decode("ascii") | ||
| 77 | + self.assertFalse(self.channel.readable()) | ||
| 78 | + self.assertTrue(self.channel.writable()) | ||
| 79 | + | ||
| 80 | + # Handle the write, which will close the socket | ||
| 81 | + self.channel.handle_write() | ||
| 82 | + self.assertTrue(self.sock.closed) | ||
| 83 | + | ||
| 84 | + data = self.sock.recv(256) | ||
| 85 | + self.assertEqual(len(data), 0) | ||
| 86 | + | ||
| 87 | |||
| 88 | class DummySock: | ||
| 89 | blocking = False | ||
