Skip to content

SO_REUSEADDR causes system-allocated ports to overlap #6209

@tamird

Description

@tamird

On Linux, the behavior of SO_REUSEADDR is ignored when the system is allocating a port. That is:

struct sockaddr_in addr = {
    .sin_family = AF_INET,
    .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
    .sin_port = htons(31337),
};

int fd1 = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, 1, sizeof(int));
bind(fd1, (const struct sockaddr*)(&addr), sizeof(addr));

int fd2 = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, 1, sizeof(int));
addr.sin_port = 0;
bind(fd2, (const struct sockaddr*)(&addr), sizeof(addr));

socklen_t addrlen = sizeof(addr);
getsockname(fd2, (struct sockaddr*)(&addr), &addrlen);
ASSERT(ntohs(addr.sin_port) != 31337);

In other words, Linux will never allocate a port that is held by another socket, regardless of SO_REUSEADDR. The same is not true on gvisor, and can cause concurrent bind calls (with SO_REUSEADDR) to receive the same system-allocated port, causing one of them to later file on a call to listen with EADDRINUSE.

Metadata

Metadata

Labels

area: networkingIssue related to networkingtype: bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions