Skip to content

Autobind of empty unix socket on Linux broken since python 3.9 #94821

Closed
@nirs

Description

@nirs

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.10only security fixes3.11only security fixes3.12only security fixes3.9only security fixestype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions