aboutsummaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-04-15 12:06:01 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-04-16 20:07:10 +0900
commitc4030a10535232988bf597759278f700d82f104b (patch)
treeaa7b001dfadec9435c6fe542700e82dcb7fa24d1 /ext
parent1826991f26249735e29b06778723f4808f0ee1dc (diff)
downloadruby-c4030a10535232988bf597759278f700d82f104b.tar.gz
ext/openssl: make OpenSSL::SSL::SSLSocket non-reusable
Fix the segmentation fault due to use after free of SSL object. Don't free the SSL object in SSLSocket#stop and leave it in RTypedData. OpenSSL::SSL::SSLSocket#stop (and the wrapper method #sysclose) was documented as "Stops the SSL connection and prepares it for another connection" and this patch changes it: once the SSLSocket stopped, it can no longer hold a new SSL connection. The method used to free the SSL object immediately after SSL_shutdown(), but it is problematic. Since some methods, such as SSLSocket#connect release the GVL while waiting the peer, there is a good chance that the SSL object is freed from another thread and this leads to a segmentation fault.
Diffstat (limited to 'ext')
-rw-r--r--ext/openssl/lib/openssl/ssl.rb5
-rw-r--r--ext/openssl/ossl_ssl.c7
2 files changed, 7 insertions, 5 deletions
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 57519f2c21..9893757011 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -290,7 +290,10 @@ module OpenSSL
# call-seq:
# ssl.sysclose => nil
#
- # Shuts down the SSL connection and prepares it for another connection.
+ # Sends "close notify" to the peer and tries to shut down the SSL
+ # connection gracefully.
+ #
+ # If sync_close is set to +true+, the underlying IO is also closed.
def sysclose
return if closed?
stop
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 96c7990046..416fa91cae 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1598,7 +1598,8 @@ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
* call-seq:
* ssl.stop => nil
*
- * Stops the SSL connection and prepares it for another connection.
+ * Sends "close notify" to the peer and tries to shut down the SSL connection
+ * gracefully.
*/
static VALUE
ossl_ssl_stop(VALUE self)
@@ -1607,14 +1608,12 @@ ossl_ssl_stop(VALUE self)
/* ossl_ssl_data_get_struct() is not usable here because it may return
* from this function; */
-
GetSSL(self, ssl);
if (ssl) {
+ /* the SSL object will be freed by GC */
ossl_ssl_shutdown(ssl);
- SSL_free(ssl);
}
- DATA_PTR(self) = NULL;
return Qnil;
}