diff options
author | Hugo van Kemenade <hugovk@users.noreply.github.com> | 2021-09-08 16:58:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-08 16:58:43 (GMT) |
commit | 59ea704df7a2fae4559e1e04f7a59d6c40f63657 (patch) | |
tree | d465a855c6325d2faeb2486a33d3183058ac6ebf | |
parent | a5610057615779ca6fc75d9e006d2fae644a94d3 (diff) | |
download | cpython-59ea704df7a2fae4559e1e04f7a59d6c40f63657.zip cpython-59ea704df7a2fae4559e1e04f7a59d6c40f63657.tar.gz cpython-59ea704df7a2fae4559e1e04f7a59d6c40f63657.tar.bz2 |
bpo-45129 Remove deprecated reuse_address (GH-28207)
Due to significant security concerns, the reuse_address parameter of
asyncio.loop.create_datagram_endpoint, deprecated in Python 3.9, is
now removed. This is because of the behavior of the socket option
SO_REUSEADDR in UDP.
Co-authored-by: Ćukasz Langa <lukasz@langa.pl>
-rw-r--r-- | Doc/library/asyncio-eventloop.rst | 38 | ||||
-rw-r--r-- | Doc/whatsnew/3.11.rst | 6 | ||||
-rw-r--r-- | Lib/asyncio/base_events.py | 27 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_base_events.py | 26 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2021-09-07-14-27-39.bpo-45129.vXH0gw.rst | 6 |
5 files changed, 33 insertions, 70 deletions
diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 147fb2b..c4408f1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -493,24 +493,9 @@ Opening network connections .. coroutinemethod:: loop.create_datagram_endpoint(protocol_factory, \ local_addr=None, remote_addr=None, *, \ family=0, proto=0, flags=0, \ - reuse_address=None, reuse_port=None, \ + reuse_port=None, \ allow_broadcast=None, sock=None) - .. note:: - The parameter *reuse_address* is no longer supported, as using - :py:data:`~sockets.SO_REUSEADDR` poses a significant security concern for - UDP. Explicitly passing ``reuse_address=True`` will raise an exception. - - When multiple processes with differing UIDs assign sockets to an - identical UDP socket address with ``SO_REUSEADDR``, incoming packets can - become randomly distributed among the sockets. - - For supported platforms, *reuse_port* can be used as a replacement for - similar functionality. With *reuse_port*, - :py:data:`~sockets.SO_REUSEPORT` is used instead, which specifically - prevents processes with differing UIDs from assigning sockets to the same - socket address. - Create a datagram connection. The socket family can be either :py:data:`~socket.AF_INET`, @@ -557,16 +542,31 @@ Opening network connections :ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples. .. versionchanged:: 3.4.4 - The *family*, *proto*, *flags*, *reuse_address*, *reuse_port, + The *family*, *proto*, *flags*, *reuse_address*, *reuse_port*, *allow_broadcast*, and *sock* parameters were added. .. versionchanged:: 3.8.1 - The *reuse_address* parameter is no longer supported due to security - concerns. + The *reuse_address* parameter is no longer supported, as using + :py:data:`~sockets.SO_REUSEADDR` poses a significant security concern for + UDP. Explicitly passing ``reuse_address=True`` will raise an exception. + + When multiple processes with differing UIDs assign sockets to an + identical UDP socket address with ``SO_REUSEADDR``, incoming packets can + become randomly distributed among the sockets. + + For supported platforms, *reuse_port* can be used as a replacement for + similar functionality. With *reuse_port*, + :py:data:`~sockets.SO_REUSEPORT` is used instead, which specifically + prevents processes with differing UIDs from assigning sockets to the same + socket address. .. versionchanged:: 3.8 Added support for Windows. + .. versionchanged:: 3.11 + The *reuse_address* parameter, disabled since Python 3.9.0, 3.8.1, + 3.7.6 and 3.6.10, has been entirely removed. + .. coroutinemethod:: loop.create_unix_connection(protocol_factory, \ path=None, *, ssl=None, sock=None, \ server_hostname=None, ssl_handshake_timeout=None) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 55ba832..64bdc0f 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -254,6 +254,12 @@ Removed Use ``bdist_wheel`` (wheel packages) instead. (Contributed by Hugo van Kemenade in :issue:`45124`.) +* Due to significant security concerns, the *reuse_address* parameter of + :meth:`asyncio.loop.create_datagram_endpoint`, disabled in Python 3.9, is + now entirely removed. This is because of the behavior of the socket option + ``SO_REUSEADDR`` in UDP. + (Contributed by Hugo van Kemenade in :issue:`45129`.) + * Remove :meth:`__getitem__` methods of :class:`xml.dom.pulldom.DOMEventStream`, :class:`wsgiref.util.FileWrapper` and :class:`fileinput.FileInput`, deprecated since Python 3.9. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 125d32d..054d7b4 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -66,10 +66,6 @@ _HAS_IPv6 = hasattr(socket, 'AF_INET6') # Maximum timeout passed to select to avoid OS limitations MAXIMUM_SELECT_TIMEOUT = 24 * 3600 -# Used for deprecation and removal of `loop.create_datagram_endpoint()`'s -# *reuse_address* parameter -_unset = object() - def _format_handle(handle): cb = handle._callback @@ -1235,7 +1231,7 @@ class BaseEventLoop(events.AbstractEventLoop): async def create_datagram_endpoint(self, protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, - reuse_address=_unset, reuse_port=None, + reuse_port=None, allow_broadcast=None, sock=None): """Create datagram connection.""" if sock is not None: @@ -1248,7 +1244,7 @@ class BaseEventLoop(events.AbstractEventLoop): # show the problematic kwargs in exception msg opts = dict(local_addr=local_addr, remote_addr=remote_addr, family=family, proto=proto, flags=flags, - reuse_address=reuse_address, reuse_port=reuse_port, + reuse_port=reuse_port, allow_broadcast=allow_broadcast) problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v) raise ValueError( @@ -1311,19 +1307,6 @@ class BaseEventLoop(events.AbstractEventLoop): exceptions = [] - # bpo-37228 - if reuse_address is not _unset: - if reuse_address: - raise ValueError("Passing `reuse_address=True` is no " - "longer supported, as the usage of " - "SO_REUSEPORT in UDP poses a significant " - "security concern.") - else: - warnings.warn("The *reuse_address* parameter has been " - "deprecated as of 3.5.10 and is scheduled " - "for removal in 3.11.", DeprecationWarning, - stacklevel=2) - for ((family, proto), (local_address, remote_address)) in addr_pairs_info: sock = None @@ -1407,7 +1390,6 @@ class BaseEventLoop(events.AbstractEventLoop): sock=None, backlog=100, ssl=None, - reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True): @@ -1438,8 +1420,6 @@ class BaseEventLoop(events.AbstractEventLoop): raise ValueError( 'host/port and sock can not be specified at the same time') - if reuse_address is None: - reuse_address = os.name == 'posix' and sys.platform != 'cygwin' sockets = [] if host == '': hosts = [None] @@ -1469,9 +1449,6 @@ class BaseEventLoop(events.AbstractEventLoop): af, socktype, proto, exc_info=True) continue sockets.append(sock) - if reuse_address: - sock.setsockopt( - socket.SOL_SOCKET, socket.SO_REUSEADDR, True) if reuse_port: _set_reuseport(sock) # Disable IPv4/IPv6 dual stack support (enabled by diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index adc7bd4..b522fac 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1794,32 +1794,6 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase): self.loop.run_until_complete(protocol.done) self.assertEqual('CLOSED', protocol.state) - def test_create_datagram_endpoint_reuse_address_error(self): - # bpo-37228: Ensure that explicit passing of `reuse_address=True` - # raises an error, as it is not safe to use SO_REUSEADDR when using UDP - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_address=True) - - with self.assertRaises(ValueError): - self.loop.run_until_complete(coro) - - def test_create_datagram_endpoint_reuse_address_warning(self): - # bpo-37228: Deprecate *reuse_address* parameter - - coro = self.loop.create_datagram_endpoint( - lambda: MyDatagramProto(create_future=True, loop=self.loop), - local_addr=('127.0.0.1', 0), - reuse_address=False) - - with self.assertWarns(DeprecationWarning): - transport, protocol = self.loop.run_until_complete(coro) - transport.close() - self.loop.run_until_complete(protocol.done) - self.assertEqual('CLOSED', protocol.state) - @patch_socket def test_create_datagram_endpoint_nosoreuseport(self, m_socket): del m_socket.SO_REUSEPORT diff --git a/Misc/NEWS.d/next/Library/2021-09-07-14-27-39.bpo-45129.vXH0gw.rst b/Misc/NEWS.d/next/Library/2021-09-07-14-27-39.bpo-45129.vXH0gw.rst new file mode 100644 index 0000000..5ba6721 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-07-14-27-39.bpo-45129.vXH0gw.rst @@ -0,0 +1,6 @@ +Due to significant security concerns, the *reuse_address* parameter of +:meth:`asyncio.loop.create_datagram_endpoint`, disabled in Python 3.9, is +now entirely removed. This is because of the behavior of the socket option +``SO_REUSEADDR`` in UDP. + +Patch by Hugo van Kemenade. |