On Fri, Jul 09, 2010 at 09:36:05AM -0500, Peter Samuelson wrote: > > [Stefan Sperling] > > This doesn't make any sense. > > I don't understand how an OS can allow a user process to break > > a system service simply by binding a socket to the same port. > > And yet ... http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx > > Once the second socket has successfully bound, the behavior for all > sockets bound to that port is indeterminate. For example, if all of > the sockets on the same port provide TCP service, any incoming TCP > connection requests over the port cannot be guaranteed to be > handled by the correct socket — the behavior is non-deterministic.
Gasp! That's just crazy. > From that article, it appears SO_REUSEADDR means something rather > different in Windows than in Unix. > > Likewise, an "active" TCP port is a port that is currently in one > of the following states: ESTABLISHED, FIN_WAIT, FIN_WAIT_2, or > LAST_ACK. Ports without SO_EXCLUSIVEADDRUSE set may be reused as > soon as the socket on which bind was previously called is closed. > > So here's how I interpret the situation: > > Windows Unix Meaning > ------------------------------------------------------------------- > default SO_REUSEADDR Can reuse a socket immediately > after you close it, without > waiting for the other end of the > connection to close (or time out) > > SO_EXCLUSIVEADDR default Cannot reuse a socket until both > ends of all connections have > closed them (or timed out) > > SO_REUSEADDR not possible Unsafe! > > Of course what we want is the first case. As far as I can tell there is little we can do to secure svnserve against this attack on Windows systems other than Server 2003, because APR won't let us set the SO_EXCLUSIVEADDR option. apr_socket_t is opaque so there seems to be no way svnserve can get at the actual socket. Not setting SO_REUSEADDR on Windows should at least fix the problem for Windows Server 2003 (patch below). Maybe we should rewrite svnserve to use the native socket API directly? I wonder how the Apache httpd server deals with this problem... Index: subversion/svnserve/main.c =================================================================== --- subversion/svnserve/main.c (revision 962479) +++ subversion/svnserve/main.c (working copy) @@ -729,9 +729,18 @@ return svn_cmdline_handle_exit_error(err, pool, "svnserve: "); } +#ifndef WIN32 /* Prevents "socket in use" errors when server is killed and quickly - * restarted. */ + * restarted. + * + * We must not set the SO_REUSEADDR socket option on Windows because + * it allows denial-of-service attacks against svnserve. + * http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx + * + * Unfortunately, APR does not support the SO_EXCLUSIVEADDRUSE option. + */ apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1); +#endif status = apr_socket_bind(sock, sa); if (status)