Skip to content

bpo-45129 Remove deprecated reuse_address #28207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions Doc/library/asyncio-eventloop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
27 changes: 2 additions & 25 deletions Lib/asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@
# 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
Expand Down Expand Up @@ -1235,7 +1231,7 @@ async def start_tls(self, transport, protocol, sslcontext, *,
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:
Expand All @@ -1248,7 +1244,7 @@ async def create_datagram_endpoint(self, protocol_factory,
# 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(
Expand Down Expand Up @@ -1311,19 +1307,6 @@ async def create_datagram_endpoint(self, protocol_factory,

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
Expand Down Expand Up @@ -1407,7 +1390,6 @@ async def create_server(
sock=None,
backlog=100,
ssl=None,
reuse_address=None,
reuse_port=None,
ssl_handshake_timeout=None,
start_serving=True):
Expand Down Expand Up @@ -1438,8 +1420,6 @@ async def create_server(
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]
Expand Down Expand Up @@ -1469,9 +1449,6 @@ async def create_server(
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
Expand Down
26 changes: 0 additions & 26 deletions Lib/test/test_asyncio/test_base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1794,32 +1794,6 @@ def test_create_datagram_endpoint_sockopts(self):
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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.