From 9e7cf9e930cb986a04e312cb576814254dff13be Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 18 Dec 2020 18:19:33 +0900 Subject: openssl is ractor-safe ossl_bn_ctx is C's global variable and it should be ractor-local to make it ractor-safe. ruby/ruby@b5588edc0a538de840c79e0bbc9d271ba0c5a711 --- ext/openssl/ossl.c | 4 ++++ ext/openssl/ossl_bn.c | 40 +++++++++++++++++++++++++++++++--------- ext/openssl/ossl_bn.h | 3 ++- 3 files changed, 37 insertions(+), 10 deletions(-) (limited to 'ext') diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 523d72e2..34c6278f 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -1126,6 +1126,10 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) void Init_openssl(void) { +#if HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + #undef rb_intern /* * Init timezone info diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 6493e051..ef26e5ce 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -9,6 +9,7 @@ */ /* modified by Michal Rokos */ #include "ossl.h" +#include #define NewBN(klass) \ TypedData_Wrap_Struct((klass), &ossl_bn_type, 0) @@ -150,12 +151,35 @@ ossl_bn_value_ptr(volatile VALUE *ptr) /* * Private */ -/* - * BN_CTX - is used in more difficult math. ops - * (Why just 1? Because Ruby itself isn't thread safe, - * we don't need to care about threads) - */ -BN_CTX *ossl_bn_ctx; + +void +ossl_bn_ctx_free(void *ptr) +{ + BN_CTX *ctx = (BN_CTX *)ptr; + BN_CTX_free(ctx); +} + +struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = { + NULL, // mark + ossl_bn_ctx_free, +}; + +rb_ractor_local_key_t ossl_bn_ctx_key; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + // stored in ractor local storage + + BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key); + if (!ctx) { + if (!(ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx); + } + return ctx; +} static VALUE ossl_bn_alloc(VALUE klass) @@ -1092,9 +1116,7 @@ Init_ossl_bn(void) eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); #endif - if (!(ossl_bn_ctx = BN_CTX_new())) { - ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); - } + ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type); eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h index a19ba194..1cc041fc 100644 --- a/ext/openssl/ossl_bn.h +++ b/ext/openssl/ossl_bn.h @@ -13,7 +13,8 @@ extern VALUE cBN; extern VALUE eBNError; -extern BN_CTX *ossl_bn_ctx; +BN_CTX *ossl_bn_ctx_get(void); +#define ossl_bn_ctx ossl_bn_ctx_get() #define GetBNPtr(obj) ossl_bn_value_ptr(&(obj)) -- cgit v1.2.3 From f2db943e8f19d4fa7bf871b9914dd9b92a5fbe6f Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Sat, 19 Dec 2020 02:04:34 +0900 Subject: support Ruby 2.x for openssl ruby/ruby@e76b56f58e44cb54497d93526d649950f5bdd1c0 --- ext/openssl/ossl.c | 7 +++++-- ext/openssl/ossl_bn.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'ext') diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 34c6278f..7bdf3a2e 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -497,8 +497,11 @@ print_mem_leaks(VALUE self) int ret; #endif - BN_CTX_free(ossl_bn_ctx); - ossl_bn_ctx = NULL; +#ifndef HAVE_RB_EXT_RACTOR_SAFE + // for Ruby 2.x + void ossl_bn_ctx_free(void); // ossl_bn.c + ossl_bn_ctx_free(); +#endif #if OPENSSL_VERSION_NUMBER >= 0x10100000 ret = CRYPTO_mem_leaks_fp(stderr); diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index ef26e5ce..d94b8e37 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -9,7 +9,10 @@ */ /* modified by Michal Rokos */ #include "ossl.h" + +#if HAVE_RB_EXT_RACTOR_SAFE #include +#endif #define NewBN(klass) \ TypedData_Wrap_Struct((klass), &ossl_bn_type, 0) @@ -152,6 +155,7 @@ ossl_bn_value_ptr(volatile VALUE *ptr) * Private */ +#if HAVE_RB_EXT_RACTOR_SAFE void ossl_bn_ctx_free(void *ptr) { @@ -180,6 +184,28 @@ ossl_bn_ctx_get(void) } return ctx; } +#else +// for ruby 2.x +static BN_CTX *gv_ossl_bn_ctx; + +BN_CTX * +ossl_bn_ctx_get(void) +{ + if (gv_ossl_bn_ctx == NULL) { + if (!(gv_ossl_bn_ctx = BN_CTX_new())) { + ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); + } + } + return gv_ossl_bn_ctx; +} + +void +ossl_bn_ctx_free(void) +{ + BN_CTX_free(gv_ossl_bn_ctx); + gv_ossl_bn_ctx = NULL; +} +#endif static VALUE ossl_bn_alloc(VALUE klass) @@ -1116,7 +1142,11 @@ Init_ossl_bn(void) eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); #endif +#ifdef HAVE_RB_EXT_RACTOR_SAFE ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type); +#else + ossl_bn_ctx_get(); +#endif eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); -- cgit v1.2.3