summaryrefslogtreecommitdiff
path: root/ext/openssl/ossl.c
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-24 16:26:22 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-24 16:26:22 +0000
commitfdd01b5356cca8da76ee32270969588dfdf9340c (patch)
treeeb0d6c1a2db76e67f146af950c3180dad15487f9 /ext/openssl/ossl.c
parent444d0910056ce7f770b81f1bd50bbcbec85c3f37 (diff)
openssl: import e72d960db262
Sync with master branch of ruby/openssl.git to import changes in v2.1.0.beta1..v2.0.6. The commit log since v2.1.0.beta1 which was imported by r59734 can be found at: https://github.com/ruby/openssl/compare/v2.1.0.beta1...e72d960db262 ---------------------------------------------------------------- Kazuki Yamaguchi (16): test/test_pair: fix test_write_nonblock{,_no_exceptions} x509name: fix a typo in docs test/test_fips: skip if setting FIPS mode fails test/test_asn1: fix possible failure in test_utctime test/test_ssl: suppress warning in test_alpn_protocol_selection_cancel test/test_pair: disable compression test/test_ssl: skip tmp_ecdh_callback test for LibreSSL >= 2.6.1 test/test_ssl: do not run NPN tests for LibreSSL >= 2.6.1 tool/ruby-openssl-docker: update test/test_pair: replace sleep with IO.select ssl: prevent SSLSocket#sysread* from leaking uninitialized data ossl.c: use struct CRYPTO_dynlock_value for non-dynamic locks ossl.c: make legacy locking callbacks reentrant test/test_engine: suppress stderr test/test_engine: check if RC4 is supported Ruby/OpenSSL 2.0.6 SHIBATA Hiroshi (1): To use upstream url of github nobu (1): ruby.h: unnormalized Fixnum value git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60013 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/openssl/ossl.c')
-rw-r--r--ext/openssl/ossl.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 6ec5e91..93ecc7d 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -517,40 +517,53 @@ print_mem_leaks(VALUE self)
/**
* Stores locks needed for OpenSSL thread safety
*/
-static rb_nativethread_lock_t *ossl_locks;
+struct CRYPTO_dynlock_value {
+ rb_nativethread_lock_t lock;
+ rb_nativethread_id_t owner;
+ size_t count;
+};
static void
-ossl_lock_unlock(int mode, rb_nativethread_lock_t *lock)
+ossl_lock_init(struct CRYPTO_dynlock_value *l)
{
- if (mode & CRYPTO_LOCK) {
- rb_nativethread_lock_lock(lock);
- } else {
- rb_nativethread_lock_unlock(lock);
- }
+ rb_nativethread_lock_initialize(&l->lock);
+ l->count = 0;
}
static void
-ossl_lock_callback(int mode, int type, const char *file, int line)
+ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l)
{
- ossl_lock_unlock(mode, &ossl_locks[type]);
+ if (mode & CRYPTO_LOCK) {
+ /* TODO: rb_nativethread_id_t is not necessarily compared with ==. */
+ rb_nativethread_id_t tid = rb_nativethread_self();
+ if (l->count && l->owner == tid) {
+ l->count++;
+ return;
+ }
+ rb_nativethread_lock_lock(&l->lock);
+ l->owner = tid;
+ l->count = 1;
+ } else {
+ if (!--l->count)
+ rb_nativethread_lock_unlock(&l->lock);
+ }
}
-struct CRYPTO_dynlock_value {
- rb_nativethread_lock_t lock;
-};
-
static struct CRYPTO_dynlock_value *
ossl_dyn_create_callback(const char *file, int line)
{
- struct CRYPTO_dynlock_value *dynlock = (struct CRYPTO_dynlock_value *)OPENSSL_malloc((int)sizeof(struct CRYPTO_dynlock_value));
- rb_nativethread_lock_initialize(&dynlock->lock);
+ /* Do not use xmalloc() here, since it may raise NoMemoryError */
+ struct CRYPTO_dynlock_value *dynlock =
+ OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));
+ if (dynlock)
+ ossl_lock_init(dynlock);
return dynlock;
}
static void
ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
{
- ossl_lock_unlock(mode, &l->lock);
+ ossl_lock_unlock(mode, l);
}
static void
@@ -566,21 +579,22 @@ static void ossl_threadid_func(CRYPTO_THREADID *id)
CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self());
}
+static struct CRYPTO_dynlock_value *ossl_locks;
+
+static void
+ossl_lock_callback(int mode, int type, const char *file, int line)
+{
+ ossl_lock_unlock(mode, &ossl_locks[type]);
+}
+
static void Init_ossl_locks(void)
{
int i;
int num_locks = CRYPTO_num_locks();
- if ((unsigned)num_locks >= INT_MAX / (int)sizeof(VALUE)) {
- rb_raise(rb_eRuntimeError, "CRYPTO_num_locks() is too big: %d", num_locks);
- }
- ossl_locks = (rb_nativethread_lock_t *) OPENSSL_malloc(num_locks * (int)sizeof(rb_nativethread_lock_t));
- if (!ossl_locks) {
- rb_raise(rb_eNoMemError, "CRYPTO_num_locks() is too big: %d", num_locks);
- }
- for (i = 0; i < num_locks; i++) {
- rb_nativethread_lock_initialize(&ossl_locks[i]);
- }
+ ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks);
+ for (i = 0; i < num_locks; i++)
+ ossl_lock_init(&ossl_locks[i]);
CRYPTO_THREADID_set_callback(ossl_threadid_func);
CRYPTO_set_locking_callback(ossl_lock_callback);