Re: Can We Agree on How to Fix SO_REUSEADDR?

Roger Espel Llima (espel@llaic.u-clermont1.fr)
Tue, 16 Feb 1999 02:14:13 +0100


George.Pajari@faximum.com (George Pajari) wrote:

> First (and less importantly) without using user threads I am not sure it
> is possible to bind and listen to multiple addresses in a single server
> app (but that may just be my ignorance of the socket API).

It is possible, and it works very well. Bind your sockets, and put
their fd's in the read set for select().

> Second, and more importantly, why break the previous semantics of
> SO_REUSEADDR which permitted one to write a server to bind to all
> addresses not already claimed without having to know all the possible
> addresses that the system might respond to?

Because of the problem of stealing ports. With SO_REUSEADDR, *if* you
do allow someone to bind to INADDR_ANY and someone else to bind to the
specific address, then the only reasonable thing to do is stop feeding
the specific address' packets to the first. This is no matter how many
interfaces you have.

So there are two choices here that make sense:

1) the old one, where this is allowed. a new app can "steal" the
connections from another one, if it bound to INADDR_ANY.

2) the new one, where this won't work. if INADDR_ANY is taken, you
can't bind again.

The change was made on the grounds that option #1 is unintuitive and can
easily lead to security holes. It's just annoying to have to find all
interfaces and bind to them, for every service that runs on a port >1024.

IMHO, there *are* situations where the laxer approach would work better;
sometimes you do trust your users (i.e it's not a public machine with
lots of shell accounts), and you might want have a default server for a
service, and more specific ones for some interfaces.

So I'd say it's reasonable to add a global flag somewhere in /proc or
sysctl, to toggle these (with the current, more secure behavior as the
default).

(note that, if that idea doesn't catch on with the networking gurus,
nothing prevents you from doing it yourself on your server; it's
probably a very simple patch).

> This is possible on all other Intel UNIX/POSIX systems I know of. It is
> no longer possible in Linux since SO_REUSEADDR was broken.

I don't think Solaris/sparc allows it, but it's been long since I played
with overlapping bind()s, so I could be mistaken. AFAIR, overlapping
IPs is more of a BSD-ism than a recognized standard Unix feature.

> Similarly, one could argue that the behaviour of preventing overlapping
> bind requests in Linux is a kludge to prevent a relatively rare security
> hole that ought to be addressed using a more elegant solution rather
> than disabling a major function of SO_REUSEADDR.

It's not that rare; just about every user-level server out there would
be affected. On some systems, nfsd itself could be affected, leading to
a trivial exploit if some other machine mounts your directories.

> Who is talking about stealing packets? I'm sure we can design the
> SO_REUSEADDR semantics that will permit overlapping bind requests without
> packets being "stolen". That is why I posed the question of how to best
> restore the semantics of SO_REUSEADDR while addressing any security
> concerns. (For example, one could permit overlapping bind requests only
> when all the processes were of the same user id.)

Looks like a bad kludge to me. Network objects and uid's have never had
any kind of tight coupling or relationship on Unix.

If we did go that way, I'd rather have an explicit option that the
INADDR_ANY server must use, i.e something like setsockopt( ... ,
SO_IPOVERLAP, &one);

-- 
Roger Espel Llima, espel@llaic.u-clermont1.fr
http://www.eleves.ens.fr:8080/home/espel/index.html

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/