Relax restriction on bind(2) to 0:port or addr:port in presence of a
connected socket with local side being addr:port. In other words, make a
TCP socket behave same way as if it always has SO_REUSEADDR set.
Practical considerations. The SO_REUSEADDR is a option that allows
bind(2) in presence of connections using the same port. It was added to
4.3BSD to allow a server restart in presence of either active or TIME-WAIT
connection(s) from the previous invocation of the server. The option is
not gratious - the old invocation doesn't need to have had SO_REUSEADDR
set, only the new one needs. In practice 99% of server software sets this
option on a socket before bind(2), as all literature and examples in the
last 40 years suggest. The option was not a security option since the
very beginning.
Security considerations. Port stealing with TCP where a local malicious
user sets up a connection before local server bind(2)s to the same port is
not possible. Two scenarios are possible:
- A local attacker bind(2)s a socket to the target port before server
does its bind(2). In that case server bind(2) will fail no matter if
SO_REUSEADDR set or not, thus server/admin is notified of an attack
attempt. The behavior is asserted by socket_afinet:multibind test and
this commit doesn't change it.
- A local attacker bind(2)s a socket to the target port and then
connect(2)s it to target remote peer address (victim). Assuming that
attacker was able to guess the port that victim is going to use in the
future connection to the server, and that victim is located behind a
firewall that would filter our SYN, the attacker would be able to create a
malicious connection in state SYN-SENT. Presence of this connection will
prevent the server's bind(2) in case the server did not set SO_REUSEADDR
(again, 99% software sets it). Thus, a local attacker can prevent server
restart, given that server listens on unpriveleged port and doesn't use
SO_REUSEADDR. This commit will change the behavior of such vulnerable
server to still be able to start in presence of this local malicious
action. So, this commit makes a vulnerable server less vulnerable to a
local DoS attack on restart.
Important note: this malicious connection in SYN-SENT will not be able to
intercept traffic. If the victim initiates its own legitimate connection
and the attacker has guessed the port right, the victims SYN will use only
the wildcard inpcb database for lookup, and will find legitimate servers
listening socket and will create a valid syncache entry. A conflict will
happen only when syncache_socket() will call in_pcbconnect() and the
latter will fail. So, in our scenario of a vulnerable local server, after
this commit a local attacker will be able to DoS particular future
connection(s) with lots of guessing, instead of reliably DoS-ing the
server restart.
Performance considerations. Removing the need to check for connected
inpcbs we basically drop the need for the port hash for TCP. This makes
it easier to implement parallelism of connect(2) for TCP, as now the TCP
inpcbs are indexed only by one database instead of two.