浏览代码

- workaround for openssl bug #1491 (multiple problems on low memory): tls
functions will preemptively fail if the available memory drops under a
certain treshold (for now a very conservative value based on the maximum
possible number of simultaneously executing connects/accepts - expect
something >= 20MB, depending on the number of processes)

Andrei Pelinescu-Onciul 18 年之前
父节点
当前提交
433e689636
共有 4 个文件被更改,包括 76 次插入12 次删除
  1. 1 2
      modules/tls/doc/tls.xml
  2. 28 6
      modules/tls/tls_init.c
  3. 1 0
      modules/tls/tls_init.h
  4. 46 4
      modules/tls/tls_server.c

+ 1 - 2
modules/tls/doc/tls.xml

@@ -73,8 +73,7 @@ route{
 			Compression is fully supported and used by default, if you have a new enough openssl version (starting with 0.9.8). Although there are some problems with zlib compression in currently deployed openssl versions (up to and including 0.9.8d, see openssl bug #1468), the tls module will automatically switch to its own fixed version. There's no need to force-disable the compression.
 			Compression is fully supported and used by default, if you have a new enough openssl version (starting with 0.9.8). Although there are some problems with zlib compression in currently deployed openssl versions (up to and including 0.9.8d, see openssl bug #1468), the tls module will automatically switch to its own fixed version. There's no need to force-disable the compression.
 		</para>
 		</para>
 		<para>
 		<para>
-			The tls module includes workarounds for the following known openssl bugs:  openssl #1204 (disable SS_OP_TLS_BLOCK_PADDING_BUG if compression is enabled, for versions between 0.9.8 and 0.9.8c), openssl #1468 (fix zlib compression memory allocation) and openssl #1467 (kerberos support will be disabled if
- openssl version less than 0.9.8e-beta1). The bug reports can be viewed at
+			The tls module includes workarounds for the following known openssl bugs:  openssl #1204 (disable SS_OP_TLS_BLOCK_PADDING_BUG if compression is enabled, for versions between 0.9.8 and 0.9.8c), openssl #1468 (fix zlib compression memory allocation), openssl #1467 (kerberos support will be disabled if the openssl version is less than 0.9.8e-beta1) and openssl #1491 (stop using tls in low memory situations due to the very high risk of openssl crashing or leaking memory). The bug reports can be viewed at
   <ulink url="http://rt.openssl.org/">http://rt.openssl.org/</ulink>.
   <ulink url="http://rt.openssl.org/">http://rt.openssl.org/</ulink>.
 		</para>
 		</para>
 		</section>
 		</section>

+ 28 - 6
modules/tls/tls_init.c

@@ -28,6 +28,12 @@
  * along with this program; if not, write to the Free Software 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
+/*
+ * History:
+ * --------
+ *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
+ *  2007-02-23  openssl low memory bugs workaround (andrei)
+ */
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/types.h>
@@ -62,7 +68,7 @@
 
 
 #if OPENSSL_VERSION_NUMBER >= 0x00908000L  /* 0.9.8*/
 #if OPENSSL_VERSION_NUMBER >= 0x00908000L  /* 0.9.8*/
 #    ifndef OPENSSL_NO_COMP
 #    ifndef OPENSSL_NO_COMP
-#        warning "openssl zlib compression bug workarround enabled"
+#        warning "openssl zlib compression bug workaround enabled"
 #    endif
 #    endif
 #    define TLS_FIX_ZLIB_COMPRESSION
 #    define TLS_FIX_ZLIB_COMPRESSION
 #    include "fixed_c_zlib.h"
 #    include "fixed_c_zlib.h"
@@ -71,7 +77,7 @@
 #ifdef TLS_KSSL_WORKARROUND
 #ifdef TLS_KSSL_WORKARROUND
 #if OPENSSL_VERSION_NUMBER < 0x00908050L
 #if OPENSSL_VERSION_NUMBER < 0x00908050L
 #	warning "openssl lib compiled with kerberos support which introduces a bug\
 #	warning "openssl lib compiled with kerberos support which introduces a bug\
- (wrong malloc/free used in kssl.c) -- attempting workarround"
+ (wrong malloc/free used in kssl.c) -- attempting workaround"
 #	warning "NOTE: if you don't link libssl staticaly don't try running the \
 #	warning "NOTE: if you don't link libssl staticaly don't try running the \
 compiled code on a system with a differently compiled openssl (it's safer \
 compiled code on a system with a differently compiled openssl (it's safer \
 to compile on the  _target_ system)"
 to compile on the  _target_ system)"
@@ -96,6 +102,7 @@ to compile on the  _target_ system)"
 #ifdef TLS_KSSL_WORKARROUND
 #ifdef TLS_KSSL_WORKARROUND
 int openssl_kssl_malloc_bug=0; /* is openssl bug #1467 present ? */
 int openssl_kssl_malloc_bug=0; /* is openssl bug #1467 present ? */
 #endif
 #endif
+int openssl_low_mem_bug=0; /* openssl bug #1491 workaround */
 int tls_disable_compression = 0; /* by default enabled */
 int tls_disable_compression = 0; /* by default enabled */
 int tls_force_run = 0; /* ignore some start-up sanity checks, use it
 int tls_force_run = 0; /* ignore some start-up sanity checks, use it
 						  at your own risk */
 						  at your own risk */
@@ -110,8 +117,10 @@ const SSL_METHOD* ssl_methods[TLS_USE_SSLv23 + 1];
 #ifdef TLS_MALLOC_DBG
 #ifdef TLS_MALLOC_DBG
 #include <execinfo.h>
 #include <execinfo.h>
 
 
-/*#define RAND_NULL_MALLOC (1024) */
+/*
+#define RAND_NULL_MALLOC (1024)
 #define NULL_GRACE_PERIOD 10U
 #define NULL_GRACE_PERIOD 10U
+*/
 
 
 
 
 inline static char* buf_append(char* buf, char* end, char* str, int str_len)
 inline static char* buf_append(char* buf, char* end, char* str, int str_len)
@@ -339,7 +348,10 @@ static int init_tls_compression(void)
 		sk_SSL_COMP_zero(comp_methods);
 		sk_SSL_COMP_zero(comp_methods);
 	}else{
 	}else{
 		ssl_version=SSLeay();
 		ssl_version=SSLeay();
-		if (ssl_version >= 0x00908000L){
+		/* replace openssl zlib compression with our version if necessary
+		 * (the openssl zlib compression uses the wrong malloc, see
+		 *  openssl #1468): 0.9.8-dev < version  <0.9.8e-beta1 */
+		if ((ssl_version >= 0x00908000L) && (ssl_version < 0x00908051L)){
 			/* the above SSL_COMP_get_compression_methods() call has the side
 			/* the above SSL_COMP_get_compression_methods() call has the side
 			 * effect of initializing the compression stack (if not already
 			 * effect of initializing the compression stack (if not already
 			 * initialized) => after it zlib is initialized and in the stack */
 			 * initialized) => after it zlib is initialized and in the stack */
@@ -512,15 +524,25 @@ int init_tls_h(void)
 	init_tls_compression();
 	init_tls_compression();
 	#ifdef TLS_KSSL_WORKARROUND
 	#ifdef TLS_KSSL_WORKARROUND
 	/* if openssl compiled with kerberos support, and openssl < 0.9.8e-dev
 	/* if openssl compiled with kerberos support, and openssl < 0.9.8e-dev
-	 * or openssl between 0.9.9-dev and 0.9.9-beta1 apply workarround for
+	 * or openssl between 0.9.9-dev and 0.9.9-beta1 apply workaround for
 	 * openssl bug #1467 */
 	 * openssl bug #1467 */
-	if (ssl_version < 0x00908051L || 
+	if (ssl_version < 0x00908050L || 
 			(ssl_version >= 0x00909000L && ssl_version < 0x00909001L)){
 			(ssl_version >= 0x00909000L && ssl_version < 0x00909001L)){
 		openssl_kssl_malloc_bug=1;
 		openssl_kssl_malloc_bug=1;
 		LOG(L_WARN, "tls: init_tls_h: openssl kerberos malloc bug detected, "
 		LOG(L_WARN, "tls: init_tls_h: openssl kerberos malloc bug detected, "
 			" kerberos support will be disabled...\n");
 			" kerberos support will be disabled...\n");
 	}
 	}
 	#endif
 	#endif
+	LOG(L_WARN, "tls: init_tls_h: openssl low memory bugs (#1491) workaround"
+				" enabled (on low memory tls operations will fail"
+				" preemptively)\n");
+	openssl_low_mem_bug=1; /* openssl bug #1491 workaround, for now
+								always enabled */
+	if (shm_available()==(unsigned long)(-1)){
+		LOG(L_WARN, "tls: ser compiled without MALLOC_STATS support:"
+				" the workaround for low mem. openssl bugs will _not_ "
+				"work\n");
+	}
 	SSL_library_init();
 	SSL_library_init();
 	SSL_load_error_strings();
 	SSL_load_error_strings();
 	init_ssl_methods();
 	init_ssl_methods();

+ 1 - 0
modules/tls/tls_init.h

@@ -43,6 +43,7 @@
 #define TLS_KSSL_WORKARROUND
 #define TLS_KSSL_WORKARROUND
 extern int openssl_kssl_malloc_bug; /* is openssl bug #1467 present ? */
 extern int openssl_kssl_malloc_bug; /* is openssl bug #1467 present ? */
 #endif
 #endif
+extern int openssl_low_mem_bug; /* openssl bug #1491 workarround */
 
 
 
 
 extern int tls_disable_compression; /* by default enabled */
 extern int tls_disable_compression; /* by default enabled */

+ 46 - 4
modules/tls/tls_server.c

@@ -31,7 +31,8 @@
 /*
 /*
  * History:
  * History:
  * --------
  * --------
- *  2007-01-26  openssl kerberos malloc bug detection/workarround (andrei)
+ *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
+ *  2007-02-23  openssl low memory bugs workaround (andrei)
  */
  */
 
 
 #include <sys/poll.h>
 #include <sys/poll.h>
@@ -43,6 +44,7 @@
 #include "../../pt.h"
 #include "../../pt.h"
 #include "../../timer.h"
 #include "../../timer.h"
 #include "../../globals.h"
 #include "../../globals.h"
+#include "../../pt.h"
 
 
 #include "tls_init.h"
 #include "tls_init.h"
 #include "tls_domain.h"
 #include "tls_domain.h"
@@ -50,6 +52,10 @@
 #include "tls_mod.h"
 #include "tls_mod.h"
 #include "tls_server.h"
 #include "tls_server.h"
 
 
+/* low memory treshold for openssl bug #1491 workaround */
+#define MIN_FREE_MEM_NEW_CONNECTION	(512*1024*get_max_procs()) /* 512k*no*/
+#define MIN_FREE_MEM_CONNECTED		(256*1024*get_max_procs()) /* 128k*no*/
+
 /* 
 /* 
  * finish the ssl init (creates the SSL and set extra_data to it)
  * finish the ssl init (creates the SSL and set extra_data to it)
  * separated from tls_tcpconn_init to allow delayed ssl context
  * separated from tls_tcpconn_init to allow delayed ssl context
@@ -61,6 +67,11 @@ static int tls_complete_init(struct tcp_connection* c)
 	struct tls_extra_data* data = 0;
 	struct tls_extra_data* data = 0;
 	tls_cfg_t* cfg;
 	tls_cfg_t* cfg;
 
 
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_NEW_CONNECTION)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		goto error2;
+	}
 	     /* Get current TLS configuration and increate reference
 	     /* Get current TLS configuration and increate reference
 	      * count immediately. There is no need to lock the structure
 	      * count immediately. There is no need to lock the structure
 	      * here, because it does not get deleted immediately. When
 	      * here, because it does not get deleted immediately. When
@@ -101,7 +112,7 @@ static int tls_complete_init(struct tcp_connection* c)
 		goto error;
 		goto error;
 	}
 	}
 #ifdef TLS_KSSL_WORKARROUND
 #ifdef TLS_KSSL_WORKARROUND
-	 /* if needed apply workarround for openssl bug #1467 */
+	 /* if needed apply workaround for openssl bug #1467 */
 	if (data->ssl->kssl_ctx && openssl_kssl_malloc_bug){
 	if (data->ssl->kssl_ctx && openssl_kssl_malloc_bug){
 		kssl_ctx_free(data->ssl->kssl_ctx);
 		kssl_ctx_free(data->ssl->kssl_ctx);
 		data->ssl->kssl_ctx=0;
 		data->ssl->kssl_ctx=0;
@@ -113,6 +124,7 @@ static int tls_complete_init(struct tcp_connection* c)
  error:
  error:
 	cfg->ref_count--;
 	cfg->ref_count--;
 	if (data) shm_free(data);
 	if (data) shm_free(data);
+ error2:
 	c->state = S_CONN_BAD;
 	c->state = S_CONN_BAD;
 	return -1;
 	return -1;
 }
 }
@@ -127,8 +139,11 @@ static int tls_update_fd(struct tcp_connection *c, int fd)
 	if (!c->extra_data && tls_complete_init(c) < 0) {
 	if (!c->extra_data && tls_complete_init(c) < 0) {
 		ERR("Delayed init failed\n");
 		ERR("Delayed init failed\n");
 		return -1;
 		return -1;
+	}else if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_CONNECTED)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		return -1;
 	}
 	}
-
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	if (SSL_set_fd(ssl, fd) != 1) {
 	if (SSL_set_fd(ssl, fd) != 1) {
 		TLS_ERR("tls_update_fd:");
 		TLS_ERR("tls_update_fd:");
@@ -276,6 +291,11 @@ static int tls_accept(struct tcp_connection *c, int* error)
 		     /* Not critical */
 		     /* Not critical */
 		return 0;
 		return 0;
 	}
 	}
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_NEW_CONNECTION)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		goto err;
+	}
 
 
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ret = SSL_accept(ssl);
 	ret = SSL_accept(ssl);
@@ -368,6 +388,11 @@ static int tls_connect(struct tcp_connection *c, int* error)
 		     /* Not critical */
 		     /* Not critical */
 		return 0;
 		return 0;
 	}
 	}
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_NEW_CONNECTION)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		goto err;
+	}
 
 
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ret = SSL_connect(ssl);
 	ret = SSL_connect(ssl);
@@ -460,6 +485,11 @@ static int tls_shutdown(struct tcp_connection *c)
 		ERR("No SSL data to perform tls_shutdown\n");
 		ERR("No SSL data to perform tls_shutdown\n");
 		return -1;
 		return -1;
 	}
 	}
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_CONNECTED)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		goto err;
+	}
 	
 	
 	ret = SSL_shutdown(ssl);
 	ret = SSL_shutdown(ssl);
 	if (ret == 1) {
 	if (ret == 1) {
@@ -530,6 +560,12 @@ static int tls_write(struct tcp_connection *c, const void *buf, size_t len, int*
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
 
 
 	err = 0;
 	err = 0;
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_CONNECTED)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		ret=-1;
+		goto err;
+	}
 	ret = SSL_write(ssl, buf, len);
 	ret = SSL_write(ssl, buf, len);
 	if (ret <= 0) {
 	if (ret <= 0) {
 		err = SSL_get_error(ssl, ret);
 		err = SSL_get_error(ssl, ret);
@@ -581,6 +617,7 @@ static int tls_write(struct tcp_connection *c, const void *buf, size_t len, int*
 		}
 		}
 	}
 	}
 
 
+err:
 	if (error) *error = err;
 	if (error) *error = err;
 	return ret;
 	return ret;
 }
 }
@@ -627,7 +664,7 @@ void tls_h_tcpconn_clean(struct tcp_connection *c)
 
 
 
 
 /*
 /*
- * perform one-way shutdown, do not wait fro notify from the remote peer 
+ * perform one-way shutdown, do not wait for notify from the remote peer 
  */
  */
 void tls_h_close(struct tcp_connection *c, int fd)
 void tls_h_close(struct tcp_connection *c, int fd)
 {
 {
@@ -767,6 +804,11 @@ int tls_h_read(struct tcp_connection * c)
 		ERR("Buffer overrun, dropping\n");
 		ERR("Buffer overrun, dropping\n");
 		r->error = TCP_REQ_OVERRUN;
 		r->error = TCP_REQ_OVERRUN;
 		return -1;
 		return -1;
+	}
+	if (openssl_low_mem_bug && (shm_available()<MIN_FREE_MEM_CONNECTED)){
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
+				" operation: %lu\n", shm_available());
+		return -1;
 	}
 	}
 	     /* we have to avoid to run in the same time 
 	     /* we have to avoid to run in the same time 
 	      * with a tls_write because of the 
 	      * with a tls_write because of the