lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAExj=OXWfxxXaSpng5OGcQTVjXGVZqR+DycvSsWaYx-bRb5mDw@mail.gmail.com>
Date:   Wed, 24 Jan 2018 10:04:49 +0000
From:   Gilberto Bertin <gilberto@...udflare.com>
To:     netdev@...r.kernel.org
Subject: SO_REUSEADDR semantics and bind conflicts

I'm trying to understand the details of SO_REUSEADDR behaviour. I think
I've found some inconsistencies in how bind conflicts are handled.
In particular, TCP and UDP behaviour seems to differ.

Let’s start with simplest TCP cases.

Case 1:

* Socket A: bound to 0.0.0.0 tcp/1234; SO_REUSEADDR absent
* Socket B: bound to 127.0.0.1 tcp/1234; SO_REUSEADDR present

(doesn't matter if both servers belong to the same uid or not)

Result: bind() fails with EADDRINUSE

This seems desired. Ok.

Case 2: What if both sockets have SO_REUSEADDR?

* Socket A: bound to 0.0.0.0 tcp/1234; SO_REUSEADDR present
* Socket B: bound to 127.0.0.1 tcp/1234; SO_REUSEADDR present

Result: bind() fails with EADDRINUSE

This seems somewhat confusing.
I would expect this one to work, unless I’m mistaken in my reading of
the socket(7) man page:

   SO_REUSEADDR
   Indicates that the rules used in validating addresses supplied in a
   bind(2) call should allow reuse of local addresses. For AF_INET sockets
   this means that a socket may bind, except when there is an active
   listening socket bound to the address. When the listening socket is
   bound to INADDR_ANY with a specific port then it is not possible to
   bind to this port for any local address.

does "except when there is an active listening socket bound to the
address" cover also the case when a socket is bound to 0.0.0.0 and
another one is bound to 127.0.0.1?

More questions arise if we repeat the same experiment with UDP sockets.

Case 3:

* Socket A: bound to 0.0.0.0 udp/1234; SO_REUSEADDR absent
* Socket B: bound 127.0.0.1 udp/1234; SO_REUSEADDR present

Result: bind() fails with EADDRINUSE

Case 4:

* Socket A: 0.0.0.0 udp/1234; SO_REUSEADDR present
* Socket B: 127.0.0.1 udp/1234; SO_REUSEADDR present

Result: bind() succeeds!

In practice this leads to a situation where:
* the INADDR_ANY server receives all the datagrams for for port 1234
 except the ones directed to 127.0.0.1
* the INADDR_LOOPBACK server receives all the datagrams for
  127.0.0.1

why is UDP behaviour different from TCP?

Another confusing case: case 5:

* Socket A: 0.0.0.0 udp/1234; SO_REUSEADDR present
* Socket B: 0.0.0.0 udp/1234; SO_REUSEADDR present

Result: bind() succeeds!

In this case all the datagrams go to the latest server that has been started.

This looks more like a bug, but again, I'd like first to understand the
exact desired semantics of SO_REUSEADDR with regard to bind conflicts.

Thanks,
gilberto

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ