Sophie

Sophie

distrib > Mageia > 4 > x86_64 > by-pkgid > 3b2566663d7163a9312af3e56a04e689 > files > 10

openssl-1.0.1e-8.8.mga4.src.rpm

From 9dbf4e95ef9491329877c628c51bcc8e644c9622 Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@imperialviolet.org>
Date: Fri, 6 Jun 2014 14:30:33 -0700
Subject: [PATCH 04/16] Fix memory leak from zero-length DTLS fragments.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The |pqueue_insert| function can fail if one attempts to insert a
duplicate sequence number. When handling a fragment of an out of
sequence message, |dtls1_process_out_of_seq_message| would not call
|dtls1_reassemble_fragment| if the fragment's length was zero. It would
then allocate a fresh fragment and attempt to insert it, but ignore the
return value, leaking the fragment.

This allows an attacker to exhaust the memory of a DTLS peer.

Fixes CVE-2014-3507

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Emilia Käsper <emilia@openssl.org>
---
 ssl/d1_both.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

Index: openssl-1.0.1e/ssl/d1_both.c
===================================================================
--- openssl-1.0.1e.orig/ssl/d1_both.c	2014-08-06 18:42:03.000000000 +0000
+++ openssl-1.0.1e/ssl/d1_both.c	2014-08-06 18:42:09.111245837 +0000
@@ -610,6 +610,9 @@
 	    msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
 		goto err;
 
+	if (frag_len == 0)
+		return DTLS1_HM_FRAGMENT_RETRY;
+
 	/* Try to find item in queue */
 	memset(seq64be,0,sizeof(seq64be));
 	seq64be[6] = (unsigned char) (msg_hdr->seq>>8);
@@ -687,7 +690,12 @@
 			i = -1;
 			}
 
-		pqueue_insert(s->d1->buffered_messages, item);
+		item = pqueue_insert(s->d1->buffered_messages, item);
+		/* pqueue_insert fails iff a duplicate item is inserted.
+		 * However, |item| cannot be a duplicate. If it were,
+		 * |pqueue_find|, above, would have returned it and control
+		 * would never have reached this branch. */
+		OPENSSL_assert(item != NULL);
 		}
 
 	return DTLS1_HM_FRAGMENT_RETRY;
@@ -745,7 +753,7 @@
 		}
 	else
 		{
-		if (frag_len && frag_len < msg_hdr->msg_len)
+		if (frag_len < msg_hdr->msg_len)
 			return dtls1_reassemble_fragment(s, msg_hdr, ok);
 
 		if (frag_len > dtls1_max_handshake_message_len(s))
@@ -774,7 +782,15 @@
 		if ( item == NULL)
 			goto err;
 
-		pqueue_insert(s->d1->buffered_messages, item);
+		item = pqueue_insert(s->d1->buffered_messages, item);
+		/* pqueue_insert fails iff a duplicate item is inserted.
+		 * However, |item| cannot be a duplicate. If it were,
+		 * |pqueue_find|, above, would have returned it. Then, either
+		 * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
+		 * to NULL and it will have been processed with
+		 * |dtls1_reassemble_fragment|, above, or the record will have
+		 * been discarded. */
+		OPENSSL_assert(item != NULL);
 		}
 
 	return DTLS1_HM_FRAGMENT_RETRY;