You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@apache.org on 2004/03/29 19:33:53 UTC

cvs commit: apache-1.3/src CHANGES

jim         2004/03/29 09:33:53

  Modified:    src/main http_main.c
               src/include ap_config.h
               src      CHANGES
  Log:
  Add in CAN-2004-0174 patch...
  
  Revision  Changes    Path
  1.611     +121 -2    apache-1.3/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v
  retrieving revision 1.610
  retrieving revision 1.611
  diff -u -r1.610 -r1.611
  --- http_main.c	16 Feb 2004 22:29:33 -0000	1.610
  +++ http_main.c	29 Mar 2004 17:33:52 -0000	1.611
  @@ -3920,6 +3920,76 @@
       old_listeners = NULL;
   }
   
  +#ifdef NONBLOCK_WHEN_MULTI_LISTEN
  +/* retrieved from APR */
  +static int soblock(int sd)
  +{
  +#ifdef NETWARE
  +    u_long one = 0;
  +
  +    if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
  +        return -1;
  +    }
  +#else
  +#ifndef BEOS
  +    int fd_flags;
  +    
  +    fd_flags = fcntl(sd, F_GETFL, 0);
  +#if defined(O_NONBLOCK)
  +    fd_flags &= ~O_NONBLOCK;
  +#elif defined(O_NDELAY)
  +    fd_flags &= ~O_NDELAY;
  +#elif defined(FNDELAY)
  +    fd_flags &= ~FNDELAY;
  +#else
  +#error Teach soblock() how to make a socket blocking on your platform.
  +#endif
  +    if (fcntl(sd, F_SETFL, fd_flags) == -1) {
  +        return errno;
  +    }
  +#else
  +    int on = 0;
  +    if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
  +        return errno;
  +#endif /* BEOS */
  +#endif /* NETWARE */
  +    return 0;
  +}
  +
  +static int sononblock(int sd)
  +{
  +#ifdef NETWARE
  +    u_long one = 1;
  +
  +    if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
  +        return -1;
  +    }
  +#else
  +#ifndef BEOS
  +    int fd_flags;
  +    
  +    fd_flags = fcntl(sd, F_GETFL, 0);
  +#if defined(O_NONBLOCK)
  +    fd_flags |= O_NONBLOCK;
  +#elif defined(O_NDELAY)
  +    fd_flags |= O_NDELAY;
  +#elif defined(FNDELAY)
  +    fd_flags |= FNDELAY;
  +#else
  +#error Teach sononblock() how to make a socket non-blocking on your platform.
  +#endif
  +    if (fcntl(sd, F_SETFL, fd_flags) == -1) {
  +        return errno;
  +    }
  +#else
  +    int on = 1;
  +    if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0)
  +        return errno;
  +#endif /* BEOS */
  +#endif /* NETWARE */
  +    return 0;
  +}
  +#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
   
   /* open sockets, and turn the listeners list into a singly linked ring */
   static void setup_listeners(pool *p)
  @@ -3952,6 +4022,20 @@
       head_listener = ap_listeners;
       close_unused_listeners();
   
  +#ifdef NONBLOCK_WHEN_MULTI_LISTEN
  +    if (ap_listeners->next != ap_listeners) {
  +        lr = ap_listeners;
  +        do {
  +            if (sononblock(lr->fd) < 0) {
  +                ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
  +                             "A listening socket could not be made non-blocking.");
  +                exit(APEXIT_INIT);
  +            }
  +            lr = lr->next;
  +        } while (lr != ap_listeners);
  +    }
  +#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
  +    
   #ifdef NO_SERIALIZED_ACCEPT
       /* warn them about the starvation problem if they're using multiple
        * sockets
  @@ -4502,6 +4586,19 @@
   #ifdef ENETUNREACH
   		case ENETUNREACH:
   #endif
  +                    /* EAGAIN/EWOULDBLOCK can be returned on BSD-derived
  +                     * TCP stacks when the connection is aborted before
  +                     * we call connect, but only because our listener
  +                     * sockets are non-blocking (NONBLOCK_WHEN_MULTI_LISTEN)
  +                     */
  +#ifdef EAGAIN
  +                case EAGAIN:
  +#endif
  +#ifdef EWOULDBLOCK
  +#if !defined(EAGAIN) || EAGAIN != EWOULDBLOCK
  +                case EWOULDBLOCK:
  +#endif
  +#endif
                       break;
   #ifdef ENETDOWN
   		case ENETDOWN:
  @@ -4591,6 +4688,21 @@
   	 * socket options, file descriptors, and read/write buffers.
   	 */
   
  +#ifdef NONBLOCK_WHEN_MULTI_LISTEN
  +        /* This assumes that on this platform the non-blocking setting of
  +         * a listening socket is inherited.  If that isn't the case,
  +         * this is wasted effort.
  +         */
  +        if (ap_listeners != ap_listeners->next) {
  +            if (soblock(csd) != 0) {
  +                ap_log_error(APLOG_MARK, APLOG_CRIT, NULL,
  +                             "couldn't make socket descriptor (%d) blocking again",
  +                             csd);
  +                continue;
  +            }
  +        }
  +#endif /* NONBLOCK_WHEN_MULTI_LISTEN */
  +
   	clen = sizeof(sa_server);
   	if (getsockname(csd, &sa_server, &clen) < 0) {
   	    ap_log_error(APLOG_MARK, APLOG_DEBUG, server_conf, 
  @@ -6365,15 +6477,22 @@
               if (csd == INVALID_SOCKET) {
                   csd = -1;
               }
  -        } while (csd < 0 && h_errno == EINTR);
  +        } while (csd < 0 && h_errno == WSAEINTR);
   	
           if (csd == INVALID_SOCKET) {
  -            if (h_errno != WSAECONNABORTED) {
  +            if ((h_errno != WSAECONNABORTED) && (h_errno != WSAEWOULDBLOCK)) {
                   ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
                                "accept: (client socket) failed with errno = %d",h_errno);
               }
           }
           else {
  +            u_long one = 0;
  +
  +            if (soblock(csd) != 0) {
  +                ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
  +                             "%d couldn't make socket descriptor (%d) blocking again.", h_errno, csd);
  +                continue;
  +            }
               add_job(csd);
           }
       }
  
  
  
  1.336     +7 -0      apache-1.3/src/include/ap_config.h
  
  Index: ap_config.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/ap_config.h,v
  retrieving revision 1.335
  retrieving revision 1.336
  diff -u -r1.335 -r1.336
  --- ap_config.h	16 Feb 2004 22:25:08 -0000	1.335
  +++ ap_config.h	29 Mar 2004 17:33:52 -0000	1.336
  @@ -151,6 +151,7 @@
   #define HAVE_SYSLOG 1
   #define SYS_SIGLIST _sys_siglist
   #define AP_ENABLE_EXCEPTION_HOOK
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #elif defined(IRIX)
   #undef HAVE_GMTOFF
  @@ -174,6 +175,7 @@
   #define NO_LONG_DOUBLE
   #define NO_LINGCLOSE
   #define HAVE_SYSLOG 1
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #elif defined(HIUX)
   #undef HAVE_GMTOFF
  @@ -259,6 +261,7 @@
   #define NET_SIZE_T size_t
   #endif
   #define AP_ENABLE_EXCEPTION_HOOK
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #elif defined(ULTRIX)
   /* we don't want to use sys/resource.h under
  @@ -285,6 +288,7 @@
   #define HAVE_SYSLOG 1
   #define HAVE_FLOCK_SERIALIZED_ACCEPT
   #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #elif defined(PARAGON)
   #define HAVE_GMTOFF 1
  @@ -977,6 +981,7 @@
   #include <sys/socket.h>
   #define NET_SIZE_T size_t
   #define NEED_HASHBANG_EMUL
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #elif defined(CYGWIN)               /* Cygwin 1.x POSIX layer for Win32 */
   #define SYSTEM_UID 18
  @@ -996,6 +1001,8 @@
   #define USE_PTHREAD_SERIALIZED_ACCEPT
   #endif
   
  +#elif defined(NETWARE)
  +#define NONBLOCK_WHEN_MULTI_LISTEN
   
   #else
   /* Unknown system - Edit these to match */
  
  
  
  1.1932    +10 -0     apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1931
  retrieving revision 1.1932
  diff -u -r1.1931 -r1.1932
  --- CHANGES	7 Mar 2004 21:47:13 -0000	1.1931
  +++ CHANGES	29 Mar 2004 17:33:52 -0000	1.1932
  @@ -1,5 +1,15 @@
   Changes with Apache 1.3.30
   
  +  *) SECURITY: CAN-2004-0174 (cve.mitre.org)
  +     Fix starvation issue on listening sockets where a short-lived
  +     connection on a rarely-accessed listening socket will cause a
  +     child to hold the accept mutex and block out new connections until
  +     another connection arrives on that rarely-accessed listening socket.
  +     Enabled for some platforms known to have the issue (accept()
  +     blocking after select() returns readable).  Define 
  +     NONBLOCK_WHEN_MULTI_LISTEN if needed for your platform and not
  +     already defined.  [Jeff Trawick, Brad Nicholes, Joe Orton]
  +
     *) SECURITY: CAN-2003-0993 (cve.mitre.org) 
        Fix parsing of Allow/Deny rules using IP addresses without a
        netmask; issue is only known to affect big-endian 64-bit