Browse code

tls: more consistent low memory checking

When checking for low memory, check for low_mem_threshold1 only
when a new connection is opened and not also during the initial
setup/key exchange. This would avoid closing partially opened ssl
connections on low memory (at least unless low_mem_threshold2 is
also exceeded).

Andrei Pelinescu-Onciul authored on 08/07/2010 15:38:09
Showing 1 changed files
... ...
@@ -129,9 +129,10 @@
129 129
 
130 130
 
131 131
 /** finish the ssl init.
132
- * Creates the SSL and set extra_data to it.
132
+ * Creates the SSL context + internal tls_extra_data and sets
133
+ * extra_data to it.
133 134
  * Separated from tls_tcpconn_init to allow delayed ssl context
134
- * init. (from the "child" process and not from the main one 
135
+ * init (from the "child" process and not from the main one).
135 136
  * WARNING: the connection should be already locked.
136 137
  * @return 0 on success, -1 on errror.
137 138
  */
... ...
@@ -217,16 +218,16 @@ static int tls_complete_init(struct tcp_connection* c)
217 217
 
218 218
 
219 219
 
220
-/** completes tls init if needed and checks if tls can be used.
220
+/** completes tls init if needed and checks if tls can be used (unsafe).
221 221
  *  It will check for low memory.
222
+ *  If it returns success, c->extra_data is guaranteed to be !=0.
222 223
  *  WARNING: must be called with c->write_lock held.
223 224
  *  @return 0 on success, < 0 on error (complete init failed or out of memory).
224 225
  */
225
-static int tls_fix_connection(struct tcp_connection* c)
226
+static int tls_fix_connection_unsafe(struct tcp_connection* c)
226 227
 {
227 228
 	if (unlikely(!c->extra_data)) {
228 229
 		if (unlikely(tls_complete_init(c) < 0)) {
229
-			ERR("Delayed init failed\n");
230 230
 			return -1;
231 231
 		}
232 232
 	}else if (unlikely(LOW_MEM_CONNECTED_TEST())){
... ...
@@ -239,6 +240,36 @@ static int tls_fix_connection(struct tcp_connection* c)
239 239
 
240 240
 
241 241
 
242
+/** completes tls init if needed and checks if tls can be used, (safe).
243
+ *  It will check for low memory.
244
+ *  If it returns success, c->extra_data is guaranteed to be !=0.
245
+ *  WARNING: must _not_ be called with c->write_lock held (it will
246
+ *   lock/unlock internally), see also tls_fix_connection_unsafe().
247
+ *  @return 0 on success, < 0 on error (complete init failed or out of memory).
248
+ */
249
+static int tls_fix_connection(struct tcp_connection* c)
250
+{
251
+	int ret;
252
+	
253
+	if (unlikely(c->extra_data == 0)) {
254
+		lock_get(&c->write_lock);
255
+			if (unlikely(c->extra_data == 0)) {
256
+				ret = tls_complete_init(c);
257
+				lock_release(&c->write_lock);
258
+				return ret;
259
+			}
260
+		lock_release(&c->write_lock);
261
+	}
262
+	if (unlikely(LOW_MEM_CONNECTED_TEST())){
263
+		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
264
+				" operation: %lu\n", shm_available());
265
+		return -1;
266
+	}
267
+	return 0;
268
+}
269
+
270
+
271
+
242 272
 /** sets an mbuf pair for the bio used by the tls connection.
243 273
  * WARNING: must be called with c->write_lock held.
244 274
  * @return 0 on success, -1 on error.
... ...
@@ -303,12 +334,6 @@ int tls_accept(struct tcp_connection *c, int* error)
303 303
 	int tls_log;
304 304
 
305 305
 	*error = SSL_ERROR_NONE;
306
-	if (unlikely(LOW_MEM_NEW_CONNECTION_TEST())){
307
-		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
308
-				" operation: %lu\n", shm_available());
309
-		goto err;
310
-	}
311
-	
312 306
 	tls_c=(struct tls_extra_data*)c->extra_data;
313 307
 	ssl=tls_c->ssl;
314 308
 	
... ...
@@ -374,12 +399,6 @@ int tls_connect(struct tcp_connection *c, int* error)
374 374
 	int tls_log;
375 375
 
376 376
 	*error = SSL_ERROR_NONE;
377
-	if (unlikely(LOW_MEM_NEW_CONNECTION_TEST())){
378
-		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
379
-				" operation: %lu\n", shm_available());
380
-		goto err;
381
-	}
382
-
383 377
 	tls_c=(struct tls_extra_data*)c->extra_data;
384 378
 	ssl=tls_c->ssl;
385 379
 	
... ...
@@ -425,7 +444,7 @@ err:
425 425
 
426 426
 
427 427
 /*
428
- * wrapper around SSL_shutdown, returns -1 on error, 0 on success 
428
+ * wrapper around SSL_shutdown, returns -1 on error, 0 on success.
429 429
  */
430 430
 static int tls_shutdown(struct tcp_connection *c)
431 431
 {
... ...
@@ -508,11 +527,17 @@ static int tls_shutdown(struct tcp_connection *c)
508 508
 
509 509
 
510 510
 
511
-/*
512
- * Called when new tcp connection is accepted or connected. It creates the ssl
513
- * data structures. There is no need to acquire any lock, because when the
514
- * connection is being created no other process has access to it yet
515
- * (this is called before adding the tcp_connection structure into the hash) 
511
+/** init tls specific data in a tcp connection.
512
+ * Called when a new tcp connection is accepted or connected.
513
+ * It completes the tcp connection initialisation by setting the tls
514
+ * specific parts.
515
+ * Note that ssl context creation and other expensive operation are left
516
+ * out (they are delayed until the first read/write).
517
+ * No locking is needed (when the connection is created no other process
518
+ * can access it).
519
+ * @param c - tcp connection.
520
+ * @param sock - socket (unused for now).
521
+ * @return  0 on success, < 0 on error.
516 522
  */
517 523
 int tls_h_tcpconn_init(struct tcp_connection *c, int sock)
518 524
 {
... ...
@@ -524,14 +549,13 @@ int tls_h_tcpconn_init(struct tcp_connection *c, int sock)
524 524
 }
525 525
 
526 526
 
527
-/*
528
- * clean the extra data upon connection shut down 
527
+/** clean the extra data upon connection shut down.
529 528
  */
530 529
 void tls_h_tcpconn_clean(struct tcp_connection *c)
531 530
 {
532 531
 	struct tls_extra_data* extra;
533 532
 	/*
534
-	* runs within global tcp lock 
533
+	* runs within global tcp lock
535 534
 	*/
536 535
 	if (c->type != PROTO_TLS) {
537 536
 		BUG("Bad connection structure\n");
... ...
@@ -553,8 +577,7 @@ void tls_h_tcpconn_clean(struct tcp_connection *c)
553 553
 }
554 554
 
555 555
 
556
-/*
557
- * perform one-way shutdown, do not wait for notify from the remote peer 
556
+/** perform one-way shutdown, do not wait for notify from the remote peer.
558 557
  */
559 558
 void tls_h_close(struct tcp_connection *c, int fd)
560 559
 {
... ...
@@ -562,7 +585,7 @@ void tls_h_close(struct tcp_connection *c, int fd)
562 562
 	struct tls_mbuf rd, wr;
563 563
 	
564 564
 	/*
565
-	 * runs either within global tcp lock or after the connection has 
565
+	 * runs either within global tcp lock or after the connection has
566 566
 	 * been "detached" and is unreachable from any other process.
567 567
 	 * Unfortunately when called via
568 568
 	 * tcpconn_put_destroy()+tcpconn_close_main_fd() the connection might
... ...
@@ -618,7 +641,7 @@ typedef int (*tcp_low_level_send_t)(int fd, struct tcp_connection *c,
618 618
  *               replaced with a static buffer).
619 619
  * @param plen - pointer to buffer size (value/result, on success it will be
620 620
  *               replaced with the size of the replacement buffer.
621
- * @param rest_buf - (result) should be filled with a pointer to the 
621
+ * @param rest_buf - (result) should be filled with a pointer to the
622 622
  *                remaining unencoded part of the original buffer if any,
623 623
  *                0 otherwise.
624 624
  * @param rest_len - (result) should be filled with the length of the
... ...
@@ -656,9 +679,10 @@ int tls_encode_f(struct tcp_connection *c,
656 656
 	offs = 0;
657 657
 	ssl_error = SSL_ERROR_NONE;
658 658
 	err_src = "TLS write:";
659
-	if (unlikely(tls_fix_connection(c) < 0)) {
659
+	if (unlikely(tls_fix_connection_unsafe(c) < 0)) {
660 660
 		/* c->extra_data might be null => exit immediately */
661
-		ERR("tls_fix_connection failed\n");
661
+		TLS_WR_TRACE("(%p) end: tls_fix_connection_unsafe failed =>"
662
+						" immediate error exit\n", c);
662 663
 		return -1;
663 664
 	}
664 665
 	tls_c = (struct tls_extra_data*)c->extra_data;
... ...
@@ -836,7 +860,7 @@ ssl_eof:
836 836
 
837 837
 /** tls read.
838 838
  * Each modification of ssl data structures has to be protected, another process * might ask for the same connection and attempt write to it which would
839
- * result in updating the ssl structures 
839
+ * result in updating the ssl structures.
840 840
  * WARNING: must be called whic c->write_lock _unlocked_.
841 841
  * @param c - tcp connection pointer. The following flags might be set:
842 842
  * @param flags - value/result:
... ...
@@ -882,20 +906,9 @@ int tls_read_f(struct tcp_connection* c, int* flags)
882 882
 	r = &c->req;
883 883
 	enc_rd_buf = 0;
884 884
 	*flags &= ~RD_CONN_REPEAT_READ;
885
-	if (unlikely(c->extra_data == 0)) {
886
-		TLS_RD_TRACE("(%p, %p) 0 extra_data => intialize\n", c, flags);
887
-		/* not yet fully init => lock & intialize */
888
-		lock_get(&c->write_lock);
889
-			if (tls_fix_connection(c) < 0) {
890
-				lock_release(&c->write_lock);
891
-				TLS_RD_TRACE("(%p, %p) end: tls_fix_connection failed =>"
892
-								" immediate error exit\n", c, flags);
893
-				return -1;
894
-			}
895
-		lock_release(&c->write_lock);
896
-	} else if (unlikely(LOW_MEM_CONNECTED_TEST())){
897
-		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
898
-			" operation: %lu\n", shm_available());
885
+	if (unlikely(tls_fix_connection(c) < 0)) {
886
+		TLS_RD_TRACE("(%p, %p) end: tls_fix_connection failed =>"
887
+						" immediate error exit\n", c, flags);
899 888
 		return -1;
900 889
 	}
901 890
 	/* here it's safe to use c->extra_data in read-only mode.
... ...
@@ -1187,7 +1200,7 @@ ssl_read_skipped:
1187 1187
 		else {
1188 1188
 			if (unlikely(bytes_free != 0)) {
1189 1189
 				/* 2i or 2ip: unconsumed input and output buffer not filled =>
1190
-				  retry ssl read (SSL_read() will read will stop at 
1190
+				  retry ssl read (SSL_read() will read will stop at
1191 1191
 				  record boundaries, unless readahead==1).
1192 1192
 				  No tcp_read() is attempted, since that would reset the
1193 1193
 				  current no-yet-consumed input data.