Description
Bug report
When using empty address for unix socket on Linux, the socket is bound to a random
address in the abstract namespace.
from unix(7):
Autobind feature
If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the
SO_PASSCRED socket option was specified for a socket that was not ex‐
plicitly bound to an address, then the socket is autobound to an ab‐
stract address. The address consists of a null byte followed by 5
bytes in the character set [0-9a-f]. Thus, there is a limit of 2^20
autobind addresses. (From Linux 2.1.15, when the autobind feature was
added, 8 bytes were used, and the limit was thus 2^32 autobind ad‐
dresses. The change to 5 bytes came in Linux 2.3.15.)
Since python 3.9, when using empty socket address (""), bind() is called with
with path.len + offsetof(struct sockaddr_un, sun_path) + 1
, so the socket is
bound to the specific address "\0" instead of a random address (e.g. "\075499").
This breaks code assuming that multiple sockets can be bound to a random address
at the same time.
In python 3.8 (not including this change):
$ python3.8
Python 3.8.13 (default, Jun 10 2022, 00:00:00)
[GCC 12.1.1 20220507 (Red Hat 12.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
>>> s.bind("")
>>> s.getsockname()
b'\x0075499'
With python 3.9 (including this change):
$ python3.9
Python 3.9.13 (main, Jun 9 2022, 00:00:00)
[GCC 12.1.1 20220507 (Red Hat 12.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
>>> s.bind("")
>>> s.getsockname()
b'\x00'
Your environment
- CPython versions tested on: python 3.9, python 3.10
- Operating system and architecture: Fedora 36, Ubuntu latest (GitHub actions)
The breaking change is f6b3a07, backported
to python 3.9. I suspect that change was not needed since it did not include
any test showing a real issue, but it is possible to fix handling of empty
unix socket address without reverting this change.