diff --git a/CVE-2024-49769-0001-Remove-test-for-getpeername.patch b/CVE-2024-49769-0001-Remove-test-for-getpeername.patch new file mode 100644 index 0000000..9ba9030 --- /dev/null +++ b/CVE-2024-49769-0001-Remove-test-for-getpeername.patch @@ -0,0 +1,34 @@ +From 75a9894ad98be6573f265859b2ea635644392a42 Mon Sep 17 00:00:00 2001 +From: Delta Regeer +Date: Sun, 3 Mar 2024 16:23:33 -0700 +Subject: Remove test for getpeername() + +--- + tests/test_wasyncore.py | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/tests/test_wasyncore.py b/tests/test_wasyncore.py +index 9c23509..a49bad4 100644 +--- a/tests/test_wasyncore.py ++++ b/tests/test_wasyncore.py +@@ -1416,17 +1416,6 @@ class Test_dispatcher(unittest.TestCase): + + return dispatcher(sock=sock, map=map) + +- def test_unexpected_getpeername_exc(self): +- sock = dummysocket() +- +- def getpeername(): +- raise socket.error(errno.EBADF) +- +- map = {} +- sock.getpeername = getpeername +- self.assertRaises(socket.error, self._makeOne, sock=sock, map=map) +- self.assertEqual(map, {}) +- + def test___repr__accepting(self): + sock = dummysocket() + map = {} +-- +2.30.2 + diff --git a/CVE-2024-49769-0002-When-closing-the-socket-set-it-to-None.patch b/CVE-2024-49769-0002-When-closing-the-socket-set-it-to-None.patch new file mode 100644 index 0000000..913a56d --- /dev/null +++ b/CVE-2024-49769-0002-When-closing-the-socket-set-it-to-None.patch @@ -0,0 +1,40 @@ +From f78ec341ac037256474220371e0163b8b308c32a Mon Sep 17 00:00:00 2001 +From: Delta Regeer +Date: Sun, 3 Mar 2024 16:37:12 -0700 +Subject: When closing the socket, set it to None + +This avoids calling close() twice on the same socket if self.close() or +self.handle_close() is called multiple times +--- + src/waitress/wasyncore.py | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/waitress/wasyncore.py b/src/waitress/wasyncore.py +index 09bcafa..f683b23 100644 +--- a/src/waitress/wasyncore.py ++++ b/src/waitress/wasyncore.py +@@ -471,6 +471,8 @@ class dispatcher: + if why.args[0] not in (ENOTCONN, EBADF): + raise + ++ self.socket = None ++ + # log and log_info may be overridden to provide more sophisticated + # logging and warning methods. In general, log is for 'hit' logging + # and 'log_info' is for informational, warning and error logging. +@@ -521,7 +523,11 @@ class dispatcher: + # handle_expt_event() is called if there might be an error on the + # socket, or if there is OOB data + # check for the error condition first +- err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) ++ err = ( ++ self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) ++ if self.socket is not None ++ else 1 ++ ) + if err != 0: + # we can get here when select.select() says that there is an + # exceptional condition on the socket +-- +2.30.2 + diff --git a/CVE-2024-49769-0003-Don-t-exit-handle_write-early-even-if-socket-is-not-.patch b/CVE-2024-49769-0003-Don-t-exit-handle_write-early-even-if-socket-is-not-.patch new file mode 100644 index 0000000..fd714fb --- /dev/null +++ b/CVE-2024-49769-0003-Don-t-exit-handle_write-early-even-if-socket-is-not-.patch @@ -0,0 +1,28 @@ +From b2c6691a88a61df7f6f65ef16da374c40000176c Mon Sep 17 00:00:00 2001 +From: Delta Regeer +Date: Sun, 3 Mar 2024 16:26:22 -0700 +Subject: Don't exit handle_write early -- even if socket is not connected + +Calling handle_close() multiple times does not hurt anything, and is +safe. +--- + src/waitress/channel.py | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/waitress/channel.py b/src/waitress/channel.py +index bc9a2bb..4a5ce3a 100644 +--- a/src/waitress/channel.py ++++ b/src/waitress/channel.py +@@ -90,9 +90,6 @@ class HTTPChannel(wasyncore.dispatcher, object): + def handle_write(self): + # Precondition: there's data in the out buffer to be sent, or + # there's a pending will_close request +- if not self.connected: +- # we dont want to close the channel twice +- return + + # try to flush any pending output + if not self.requests: +-- +2.30.2 + diff --git a/CVE-2024-49769-0004-Assume-socket-is-not-connected-when-passed-to-wasync.patch b/CVE-2024-49769-0004-Assume-socket-is-not-connected-when-passed-to-wasync.patch new file mode 100644 index 0000000..6dbeeb0 --- /dev/null +++ b/CVE-2024-49769-0004-Assume-socket-is-not-connected-when-passed-to-wasync.patch @@ -0,0 +1,51 @@ +From ccef33f7726247a7b79e8b7e7920dd2014c58f64 Mon Sep 17 00:00:00 2001 +From: Delta Regeer +Date: Sun, 3 Mar 2024 16:16:48 -0700 +Subject: Assume socket is not connected when passed to wasyncore.dispatcher + +No longer call getpeername() on the remote socket either, as it is not +necessary for any of the places where waitress requires that self.addr +in a subclass of the dispatcher needs it. + +This removes a race condition when setting up a HTTPChannel where we +accepted the socket, and know the remote address, yet call getpeername() +again which would have the unintended side effect of potentially setting +self.connected to False because the remote has already shut down part of +the socket. + +This issue was uncovered in #418, where the server would go into a hard +loop because self.connected was used in various parts of the code base. +--- + src/waitress/wasyncore.py | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/src/waitress/wasyncore.py b/src/waitress/wasyncore.py +index f683b23..dfd38dd 100644 +--- a/src/waitress/wasyncore.py ++++ b/src/waitress/wasyncore.py +@@ -300,22 +300,6 @@ class dispatcher: + # get a socket from a blocking source. + sock.setblocking(0) + self.set_socket(sock, map) +- self.connected = True +- # The constructor no longer requires that the socket +- # passed be connected. +- try: +- self.addr = sock.getpeername() +- except socket.error as err: +- if err.args[0] in (ENOTCONN, EINVAL): +- # To handle the case where we got an unconnected +- # socket. +- self.connected = False +- else: +- # The socket is broken in some unknown way, alert +- # the user and remove it from the map (to prevent +- # polling of broken sockets). +- self.del_channel(map) +- raise + else: + self.socket = None + +-- +2.30.2 + diff --git a/CVE-2024-49769-0005-HTTPChannel-is-always-created-from-accept-explicitly.patch b/CVE-2024-49769-0005-HTTPChannel-is-always-created-from-accept-explicitly.patch new file mode 100644 index 0000000..b714971 --- /dev/null +++ b/CVE-2024-49769-0005-HTTPChannel-is-always-created-from-accept-explicitly.patch @@ -0,0 +1,27 @@ +From ad198816fb728ea0aec2c20b2c87396e862004e8 Mon Sep 17 00:00:00 2001 +From: Delta Regeer +Date: Sun, 3 Mar 2024 16:15:51 -0700 +Subject: HTTPChannel is always created from accept, explicitly set + self.connected to True + +--- + src/waitress/channel.py | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/waitress/channel.py b/src/waitress/channel.py +index 4a5ce3a..62ca9fa 100644 +--- a/src/waitress/channel.py ++++ b/src/waitress/channel.py +@@ -77,8 +77,7 @@ class HTTPChannel(wasyncore.dispatcher, object): + self.outbuf_lock = threading.Condition() + + wasyncore.dispatcher.__init__(self, sock, map=map) +- +- # Don't let wasyncore.dispatcher throttle self.addr on us. ++ self.connected = True + self.addr = addr + + def writable(self): +-- +2.30.2 + diff --git a/python-waitress.spec b/python-waitress.spec index 7191ecd..9d9910e 100644 --- a/python-waitress.spec +++ b/python-waitress.spec @@ -1,12 +1,18 @@ %global _docdir_fmt %{name} Name: python-waitress -Version: 1.1.0 -Release: 5 +Version: 1.4.4 +Release: 1 Summary: A WSGI server for Python 2 and 3 -License: ZPLv2.1 +License: ZPL-2.1 URL: https://github.com/Pylons/waitress Source0: https://github.com/Pylons/waitress/archive/v%{version}/waitress-%{version}.tar.gz +# https://lists.debian.org/debian-lts-announce/2024/11/msg00012.html +Patch0: CVE-2024-49769-0001-Remove-test-for-getpeername.patch +Patch1: CVE-2024-49769-0002-When-closing-the-socket-set-it-to-None.patch +Patch2: CVE-2024-49769-0003-Don-t-exit-handle_write-early-even-if-socket-is-not-.patch +Patch3: CVE-2024-49769-0004-Assume-socket-is-not-connected-when-passed-to-wasync.patch +Patch4: CVE-2024-49769-0005-HTTPChannel-is-always-created-from-accept-explicitly.patch BuildArch: noarch %description @@ -41,7 +47,7 @@ and Windows under Python 2.7+ and Python 3.5+. It is also known to run on PyPy 1.6.0+ on UNIX. It supports HTTP/1.0 and HTTP/1.1. %prep -%autosetup -n waitress-%{version} +%autosetup -n waitress-%{version} -p1 %build %py2_build @@ -63,5 +69,9 @@ on PyPy 1.6.0+ on UNIX. It supports HTTP/1.0 and HTTP/1.1. %{python3_sitelib}/* %changelog +* Tue Apr 15 2025 yaoxin <1024769339@qq.com> - 1.4.4-1 +- Update to 1.4.4 for fix CVE-2019-16785,CVE-2019-16786,CVE-2019-16789 and CVE-2019-16792 +- Add patches for CVE-2024-49769: DoS due to resource exhaustion + * Thu Feb 13 2020 Ruijun Ge - 1.1.0-5 - init package diff --git a/waitress-1.1.0.tar.gz b/waitress-1.1.0.tar.gz deleted file mode 100644 index 727b2d6..0000000 Binary files a/waitress-1.1.0.tar.gz and /dev/null differ diff --git a/waitress-1.4.4.tar.gz b/waitress-1.4.4.tar.gz new file mode 100644 index 0000000..c4eb84c Binary files /dev/null and b/waitress-1.4.4.tar.gz differ