* fhandler_socket.cc (fhandler_socket::bind): Don't run explicit

local socket test in SO_REUSEADDR case on systems supporting
	enhanced socket security.  Explain why.  Only call address_in_use
	for AF_INET sockets.
	* net.cc (cygwin_setsockopt): Don't call setsockopt to set SO_REUSEADDR
	on systems supporting enhanced socket security.  Add comment.
	* wincap.h (wincaps::has_enhanced_socket_security): New element.
	* wincap.cc: Implement above element throughout.
This commit is contained in:
Corinna Vinschen 2008-07-08 20:12:46 +00:00
parent b8fbf5d4c4
commit 23672785ee
5 changed files with 50 additions and 7 deletions

View File

@ -1,3 +1,14 @@
2008-07-08 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::bind): Don't run explicit
local socket test in SO_REUSEADDR case on systems supporting
enhanced socket security. Explain why. Only call address_in_use
for AF_INET sockets.
* net.cc (cygwin_setsockopt): Don't call setsockopt to set SO_REUSEADDR
on systems supporting enhanced socket security. Add comment.
* wincap.h (wincaps::has_enhanced_socket_security): New element.
* wincap.cc: Implement above element throughout.
2008-07-08 Corinna Vinschen <corinna@vinschen.de> 2008-07-08 Corinna Vinschen <corinna@vinschen.de>
* net.cc (ipv6_inited): Make NO_COPY. * net.cc (ipv6_inited): Make NO_COPY.

View File

@ -911,17 +911,29 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
(const char *) &on, sizeof on); (const char *) &on, sizeof on);
debug_printf ("%d = setsockopt (SO_EXCLUSIVEADDRUSE), %E", ret); debug_printf ("%d = setsockopt (SO_EXCLUSIVEADDRUSE), %E", ret);
} }
else else if (!wincap.has_enhanced_socket_security ())
{ {
debug_printf ("SO_REUSEADDR set"); debug_printf ("SO_REUSEADDR set");
/* There's a bug in SO_REUSEADDR handling in WinSock. /* There's a bug in SO_REUSEADDR handling in WinSock.
Per standards, we must not be able to reuse a complete Per standards, we must not be able to reuse a complete
duplicate of a local TCP address (same IP, same port), duplicate of a local TCP address (same IP, same port),
even if SO_REUSEADDR has been set. That's unfortunately even if SO_REUSEADDR has been set. That's unfortunately
possible in WinSock. So we're testing here if the local possible in WinSock.
address is already in use and don't bind, if so. This
only works for OSes with IP Helper support. */ So we're testing here if the local address is already in
if (get_socket_type () == SOCK_STREAM use and don't bind, if so. This only works for OSes with
IP Helper support and is, of course, still prone to races.
However, we don't have to do this on systems supporting
"enhanced socket security" (2K3 and later). On these
systems the default binding behaviour is exactly as you'd
expect for SO_REUSEADDR, while setting SO_REUSEADDR re-enables
the wrong behaviour. So all we have to do on these newer
systems is never to set SO_REUSEADDR but only to note that
it has been set for the above SO_EXCLUSIVEADDRUSE setting.
See setsockopt() in net.cc. */
if (name->sa_family == AF_INET
&& get_socket_type () == SOCK_STREAM
&& wincap.has_ip_helper_lib () && wincap.has_ip_helper_lib ()
&& address_in_use ((struct sockaddr_in *) name)) && address_in_use ((struct sockaddr_in *) name))
{ {

View File

@ -649,8 +649,16 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES) if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname); optname = convert_ws1_ip_optname (optname);
res = setsockopt (fh->get_socket (), level, optname, /* On systems supporting "enhanced socket security (2K3 and later),
(const char *) optval, optlen); the default behaviour of socket binding is equivalent to the POSIX
behaviour with SO_REUSEADDR. Setting SO_REUSEADDR would only result
in wrong behaviour. See also fhandler_socket::bind(). */
if (level == SOL_SOCKET && optname == SO_REUSEADDR
&& wincap.has_enhanced_socket_security ())
res = 0;
else
res = setsockopt (fh->get_socket (), level, optname,
(const char *) optval, optlen);
if (optlen == 4) if (optlen == 4)
syscall_printf ("setsockopt optval=%x", *(long *) optval); syscall_printf ("setsockopt optval=%x", *(long *) optval);

View File

@ -33,6 +33,7 @@ static NO_COPY wincaps wincap_unknown = {
has_disabled_user_tos_setting:false, has_disabled_user_tos_setting:false,
has_fileid_dirinfo:false, has_fileid_dirinfo:false,
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true, needs_logon_sid_in_sid_list:true,
@ -64,6 +65,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_disabled_user_tos_setting:false, has_disabled_user_tos_setting:false,
has_fileid_dirinfo:false, has_fileid_dirinfo:false,
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true, needs_logon_sid_in_sid_list:true,
@ -95,6 +97,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_disabled_user_tos_setting:false, has_disabled_user_tos_setting:false,
has_fileid_dirinfo:false, has_fileid_dirinfo:false,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true, needs_logon_sid_in_sid_list:true,
@ -126,6 +129,7 @@ static NO_COPY wincaps wincap_2000 = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:true, has_buggy_restart_scan:true,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true, needs_logon_sid_in_sid_list:true,
@ -157,6 +161,7 @@ static NO_COPY wincaps wincap_2000sp4 = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:true, has_buggy_restart_scan:true,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true, needs_logon_sid_in_sid_list:true,
@ -188,6 +193,7 @@ static NO_COPY wincaps wincap_xp = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false, needs_logon_sid_in_sid_list:false,
@ -219,6 +225,7 @@ static NO_COPY wincaps wincap_xpsp1 = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false, needs_logon_sid_in_sid_list:false,
@ -250,6 +257,7 @@ static NO_COPY wincaps wincap_xpsp2 = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false, needs_logon_sid_in_sid_list:false,
@ -281,6 +289,7 @@ static NO_COPY wincaps wincap_2003 = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false, needs_logon_sid_in_sid_list:false,
@ -312,6 +321,7 @@ static NO_COPY wincaps wincap_vista = {
has_disabled_user_tos_setting:true, has_disabled_user_tos_setting:true,
has_fileid_dirinfo:true, has_fileid_dirinfo:true,
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_enhanced_socket_security:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:true, has_mandatory_integrity_control:true,
needs_logon_sid_in_sid_list:false, needs_logon_sid_in_sid_list:false,

View File

@ -31,6 +31,7 @@ struct wincaps
unsigned has_disabled_user_tos_setting : 1; unsigned has_disabled_user_tos_setting : 1;
unsigned has_fileid_dirinfo : 1; unsigned has_fileid_dirinfo : 1;
unsigned has_exclusiveaddruse : 1; unsigned has_exclusiveaddruse : 1;
unsigned has_enhanced_socket_security : 1;
unsigned has_buggy_restart_scan : 1; unsigned has_buggy_restart_scan : 1;
unsigned has_mandatory_integrity_control : 1; unsigned has_mandatory_integrity_control : 1;
unsigned needs_logon_sid_in_sid_list : 1; unsigned needs_logon_sid_in_sid_list : 1;
@ -78,6 +79,7 @@ public:
bool IMPLEMENT (has_disabled_user_tos_setting) bool IMPLEMENT (has_disabled_user_tos_setting)
bool IMPLEMENT (has_fileid_dirinfo) bool IMPLEMENT (has_fileid_dirinfo)
bool IMPLEMENT (has_exclusiveaddruse) bool IMPLEMENT (has_exclusiveaddruse)
bool IMPLEMENT (has_enhanced_socket_security)
bool IMPLEMENT (has_buggy_restart_scan) bool IMPLEMENT (has_buggy_restart_scan)
bool IMPLEMENT (has_mandatory_integrity_control) bool IMPLEMENT (has_mandatory_integrity_control)
bool IMPLEMENT (needs_logon_sid_in_sid_list) bool IMPLEMENT (needs_logon_sid_in_sid_list)