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)

Reply via email to