Bug #14780 memory leak for mysql 4.1.14 with openssl enabled
Submitted: 9 Nov 2005 8:44 Modified: 9 Dec 2005 0:23
Reporter: Aleksey Kishkin Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:4.1 OS:Linux (linux)
Assigned to: Sergey Glukhov

[9 Nov 2005 8:44] Aleksey Kishkin
Description:
as of our customer reports:

We recompiled 4.1.14 source with ssl support. Following mysql manual, we turned on -  Compiler is gcc 3.2.3, openssl is 0.9.7a-2. We saw memory leak after a connection is closed. This prevented our application from running more than a day (we don't keep permanent connections).
 
 To illustrate, we run valgrind (2.4.0) on mysql client binary from 4.1.14. Here is what valgrind says:
 
 ==21807== 42403 (272 direct, 42131 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 20
 ==21807== at 0x1B9034C4: malloc (vg_replace_malloc.c:130)
 ==21807== by 0x1BA1729F: (within /lib/libcrypto.so.0.9.7a)
 ==21807== by 0x1BA178FB: CRYPTO_malloc (in /lib/libcrypto.so.0.9.7a)
 ==21807== by 0x1B9D1B60: SSL_new (in /lib/libssl.so.0.9.7a)
 ==21807== by 0x80938EB: sslconnect (in /usr/bin/mysql)
 ==21807== by 0x8090866: mysql_real_connect (in /usr/bin/mysql)
 ==21807== by 0x805C463: (within /usr/bin/mysql)
 ==21807== by 0x805C6B7: (within /usr/bin/mysql)
 ==21807== by 0x805789C: main (in /usr/bin/mysql)
 ==21807==
 ==21807==
 ==21807== 18437 bytes in 1 blocks are possibly lost in loss record 19 of 20
 ==21807== at 0x1B9034C4: malloc (vg_replace_malloc.c:130)
 ==21807== by 0x1BA1729F: (within /lib/libcrypto.so.0.9.7a)
 ==21807== by 0x1BA178FB: CRYPTO_malloc (in /lib/libcrypto.so.0.9.7a)
 ==21807== by 0x1B9CE2A4: ssl3_setup_buffers (in /lib/libssl.so.0.9.7a)
 ==21807== by 0x1B9C654C: ssl3_connect (in /lib/libssl.so.0.9.7a)
 ==21807== by 0x1B9D45DC: SSL_do_handshake (in /lib/libssl.so.0.9.7a)
 ==21807== by 0x8093994: sslconnect (in /usr/bin/mysql)
 ==21807== by 0x8090866: mysql_real_connect (in /usr/bin/mysql)
 ==21807== by 0x805C463: (within /usr/bin/mysql)
 ==21807== by 0x805C6B7: (within /usr/bin/mysql)
 ==21807== by 0x805789C: main (in /usr/bin/mysql)
 
 
 After digging into source code, it appears that this is caused by the following chain of calls:
 
 vio_close (viosocket.c:227)
 vio_ssl_delete (viossl.c:86)
 end_server (client.c:844)
 mysql_close
 
 What vio_ssl_delete() should have done is to call vio_ssl_close(), which will free vio->ssl_arg (which was allocated by SSL_new, etc.). However, because of #define DONT_MAP_VIO at the beginning of vio_priv.h, vio_close() is not redirected to vio_ssl_close(), therefore the SSL block is never freed, hence the leak.
 
 

How to repeat:
compile mysql with --with-vio --with-openssl. run valgrind on mysql client binary.

Suggested fix:
One solution would be to do the same in vio_ssl_delete as in vio_delete(), i.e.:
 #ifdef HAVE_VIO /*WAX*/
 vio->vioclose(vio);
 #else
 vio_close(vio);
 #endif
[9 Nov 2005 17:56] Haobo Yu
After the following patch:

--- mysql-4.1.14/vio/viossl.c   2005-11-08 22:16:48.000000000 -0800
+++ mysql-4.1.14/vio/viossl.c   2005-11-08 22:18:16.000000000 -0800
@@ -83,7 +83,11 @@
   if (vio)
   {
     if (vio->type != VIO_CLOSED)
+#ifdef HAVE_VIO /* WAX */
+      vio->vioclose(vio);
+#else
       vio_close(vio);
+#endif
     my_free((gptr) vio,MYF(0));
   }
 }

There are still memory leaks.  It seems that the SSL context allocated during mysql_real_connect() isn't freed by mysql_close().  Here is what valgrind says:

==26144== 11779 (248 direct, 11531 indirect) bytes in 1 blocks are definitely lost in loss  record 11 of 18
==26144==    at 0x1B9034C4: malloc (vg_replace_malloc.c:130)
==26144==    by 0x1BA1729F: (within /lib/libcrypto.so.0.9.7a)
==26144==    by 0x1BA178FB: CRYPTO_malloc (in /lib/libcrypto.so.0.9.7a)
==26144==    by 0x1B9D387E: SSL_CTX_new (in /lib/libssl.so.0.9.7a)
==26144==    by 0x8093D11: new_VioSSLConnectorFd (in /usr/bin/mysql)
==26144==    by 0x8090826: mysql_real_connect (in /usr/bin/mysql)
==26144==    by 0x805C463: (within /usr/bin/mysql)
==26144==    by 0x805C6B7: (within /usr/bin/mysql)
==26144==    by 0x805789C: main (in /usr/bin/mysql)
[9 Nov 2005 21:01] Haobo Yu
The following patch fixed SSL context leaks.

--- include/violite.h   2005-11-09 10:38:46.000000000 -0800
+++ include/violite.h   2005-11-09 10:42:31.000000000 -0800
@@ -118,6 +118,7 @@
 *new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
                       const char *ca_file,  const char *ca_path,
                       const char *cipher);
+void free_VioSSLConnectorFd(struct st_VioSSLConnectorFd*);
 struct st_VioSSLAcceptorFd
 *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
                      const char *ca_file,const char *ca_path,
--- sql-common/client.c 2005-11-09 10:41:39.000000000 -0800
+++ sql-common/client.c 2005-11-09 10:41:39.000000000 -0800
@@ -1492,7 +1492,9 @@
   my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
   my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
   my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
-  my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
+#ifdef HAVE_OPENSSL
+  free_VioSSLConnectorFd(mysql->connector_fd);
+#endif
   mysql->options.ssl_key = 0;
   mysql->options.ssl_cert = 0;
   mysql->options.ssl_ca = 0;
--- vio/viosslfactories.c       2005-11-09 10:38:56.000000000 -0800
+++ vio/viosslfactories.c       2005-11-09 10:45:07.000000000 -0800
@@ -207,6 +207,16 @@
        Add option --verify to mysql to be able to change verification mode
 */

+void
+free_VioSSLConnectorFd(struct st_VioSSLConnectorFd* st)
+{
+  if (st) {
+    SSL_CTX_free(st->ssl_context);
+    st->ssl_context = 0;
+  }
+  my_free((gptr)st,MYF(MY_ALLOW_ZERO_PTR));
+}
+
 struct st_VioSSLConnectorFd *
 new_VioSSLConnectorFd(const char* key_file,
                      const char* cert_file,
[15 Nov 2005 13:16] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/32270
[21 Nov 2005 12:06] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/32452
[21 Nov 2005 12:08] Sergey Glukhov
Fixed in 4.1.16
[9 Dec 2005 0:23] Paul Dubois
Noted in 4.1.16 changelog.