From 222f0d2d94be8b92c306c062320fd15b59a9000a Mon Sep 17 00:00:00 2001
From: Todd Short <tshort@akamai.com>
Date: Wed, 1 Apr 2015 11:12:06 -0400
Subject: [PATCH 21/26] RT3881 Instrument OpenSSL buffer heap memory usage

Added function to register callbacks to allocate and free data buffers.
These callbacks can then allocate and free the memory as needed, while
also recording buffer allocations.

(cherry picked from commit 2f5157133947cb02fd18635be49f1f9fa6fe306a)

Conflicts:
	include/openssl/ssl.h
	ssl/s3_both.c
---
 doc/ssl/SSL3_BUFFER_set_mem_functions.pod | 60 +++++++++++++++++++++++++++++++
 include/openssl/ssl.h                     |  3 ++
 ssl/record/ssl3_buffer.c                  | 40 ++++++++++++++++++---
 3 files changed, 99 insertions(+), 4 deletions(-)
 create mode 100644 doc/ssl/SSL3_BUFFER_set_mem_functions.pod

diff --git a/doc/ssl/SSL3_BUFFER_set_mem_functions.pod b/doc/ssl/SSL3_BUFFER_set_mem_functions.pod
new file mode 100644
index 0000000..6238150
--- /dev/null
+++ b/doc/ssl/SSL3_BUFFER_set_mem_functions.pod
@@ -0,0 +1,60 @@
+=pod
+
+=head1 NAME
+
+SSL3_BUFFER_set_mem_functions() - specify buffer allocation/free functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ SSL3_BUFFER_set_mem_functions(void *(*m_cb)(int, size_t), void (*f_cb)(int, size_t, void*));
+
+ void *(*m_cb)(int rw, size_t size);
+ void (*f_cb)(int rw, size_t size, void* ptr);
+
+=head1 DESCRIPTION
+
+SSL3_BUFFER_set_mem_functions() sets the B<m_cb> and B<f_cb> callbacks
+that are used to allocate and free the data buffers used in the SSL
+struture.
+
+The B<m_cb> callback is used for allocation of data buffers. Setting
+this value to NULL restores the default allocator.
+
+When the B<m_cb()> callback is invoked, the B<rw> parameter is 1 for
+read buffers, and 0 for write buffers. The B<size> parameter is the
+expected allocation to be returned by the callback.
+
+The B<f_cb> callback is used to free data buffers. Setting this
+value to NULL restores the default freer.
+
+When the B<f_cb()> callback is invoked, the B<rw> parameter is 1 for
+read buffers, and 0 for write buffers. The B<size> parameter is the
+size of the allocation to be freed. The B<ptr> parameter is the
+buffer pointer to be freed.
+
+=head1 NOTES
+
+The B<m_cb> callback is to allocate memory. The B<f_cb> callback is to
+free memory. This memory can be regular heap memory, or from a special
+memory region. These callbacks may also be used to track the amount of
+buffer memory being used by OpenSSL.
+
+These functions should be set once at OpenSSL initialization, before
+L<SSL_new(3)|SSL_new(3)> is called.
+
+=head1 RETURN VALUES
+
+The SSL3_BUFFER_set_mem_functions() function has no return value.
+
+The B<m_cb()> callback function returns a freshly allocated data buffer
+or NULL on failure.
+
+The B<f_cb()> callback function has no return value.
+
+=head1 SEE ALSO
+
+L<ssl(3)|ssl(3)>, L<SSL_new(3)|SSL_new(3)>
+
+=cut
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index b4ecfa1..731d0a4 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2002,6 +2002,9 @@ __owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
 # endif
 
 void SSL_CTX_share_session_cache(SSL_CTX *a, SSL_CTX *b);
+/* SSL3 buffer allocation routine */
+/* The int argument is 1 for read buffers, 0 for write buffers */
+void SSL3_BUFFER_set_mem_functions(void* (*m)(int, size_t), void(*f)(int, size_t, void*));
 
 /* BEGIN ERROR CODES */
 /*
diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c
index 66fb721..ef678e8 100644
--- a/ssl/record/ssl3_buffer.c
+++ b/ssl/record/ssl3_buffer.c
@@ -112,6 +112,38 @@
 #include "../ssl_locl.h"
 #include "record_locl.h"
 
+
+
+/*
+ * Add user-definable version buffer allocation/free.
+ * With this, users are able to define and record data-buffer
+ * allocations separately from regular memory allocations.
+ */
+static void* (*buffer_malloc_cb)(int, size_t) = NULL;
+static void (*buffer_free_cb)(int, size_t, void*) = NULL;
+
+static void* ssl3_buffer_malloc(int for_read, size_t sz)
+{
+    if (buffer_malloc_cb)
+        return (*buffer_malloc_cb)(for_read, sz);
+
+    return OPENSSL_malloc(sz);
+}
+
+static void ssl3_buffer_free(int for_read, size_t sz, void *mem)
+{
+    if (buffer_free_cb)
+        (*buffer_free_cb)(for_read, sz, mem);
+    else
+        OPENSSL_free(mem);
+}
+
+void SSL3_BUFFER_set_mem_functions(void* (*m)(int, size_t), void(*f)(int, size_t, void*))
+{
+    buffer_malloc_cb = m;
+    buffer_free_cb = f;
+}
+
 void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n)
 {
     if (d != NULL)
@@ -167,7 +199,7 @@ int ssl3_setup_read_buffer(SSL *s)
         if (ssl_allow_compression(s))
             len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
 #endif
-        if ((p = OPENSSL_malloc(len)) == NULL)
+        if ((p = ssl3_buffer_malloc(1, len)) == NULL)
             goto err;
         b->buf = p;
         b->len = len;
@@ -208,7 +240,7 @@ int ssl3_setup_write_buffer(SSL *s)
         if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
             len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
 
-        if ((p = OPENSSL_malloc(len)) == NULL)
+        if ((p = ssl3_buffer_malloc(0, len)) == NULL)
             goto err;
         wb->buf = p;
         wb->len = len;
@@ -236,7 +268,7 @@ int ssl3_release_write_buffer(SSL *s)
 
     wb = RECORD_LAYER_get_wbuf(&s->rlayer);
 
-    OPENSSL_free(wb->buf);
+    ssl3_buffer_free(0, wb->len, wb->buf);
     wb->buf = NULL;
     return 1;
 }
@@ -246,7 +278,7 @@ int ssl3_release_read_buffer(SSL *s)
     SSL3_BUFFER *b;
 
     b = RECORD_LAYER_get_rbuf(&s->rlayer);
-    OPENSSL_free(b->buf);
+    ssl3_buffer_free(1, b->len, b->buf);
     b->buf = NULL;
     return 1;
 }
-- 
2.3.2 (Apple Git-55)

