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