ruby-changes:50714
From: usa <ko1@a...>
Date: Thu, 22 Mar 2018 12:34:02 +0900 (JST)
Subject: [ruby-changes:50714] usa:r62885 (ruby_2_3): merge https://github.com/ruby/openssl/commit/3af2635f117f8da563d180bc1c58702aecb16e0c
usa 2018-03-22 12:33:56 +0900 (Thu, 22 Mar 2018) New Revision: 62885 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62885 Log: merge https://github.com/ruby/openssl/commit/3af2635f117f8da563d180bc1c58702aecb16e0c patched by Kazuki Yamaguchi <k@r...> bio: prevent possible GC issue in ossl_obj2bio() Prevent the new object created by StringValue() from being GCed. Luckily, as none of the callers of ossl_obj2bio() reads from the returned BIO after possible triggering GC, this has not been a real problem. As a bonus, ossl_protect_obj2bio() function which is no longer used anywhere is removed. merge https://github.com/ruby/openssl/commit/f842b0d5c5e37527c11954a4b7a98c8d9cc57865 patched by Kazuki Yamaguchi <k@r...> bio: do not use the FILE BIO method in ossl_obj2bio() Read everything from an IO object into a String first and use the memory buffer BIO method just as we do for String inputs. For MSVC builds, the FILE BIO method uses the "UPLINK" interface that requires the application to provide OPENSSL_Applink() function. For us, the "application" means ruby.exe, in which we can't do anything. As a workaround, avoid using the FILE BIO method at all. Usually private keys or X.509 certificates aren't that large and the temporarily increased memory usage hopefully won't be an issue. ext/openssl/ossl_version.h (OpenSSL::VERSION): bump to 1.1.1. Modified files: branches/ruby_2_3/ChangeLog branches/ruby_2_3/ext/openssl/ossl_bio.c branches/ruby_2_3/ext/openssl/ossl_bio.h branches/ruby_2_3/ext/openssl/ossl_config.c branches/ruby_2_3/ext/openssl/ossl_pkcs12.c branches/ruby_2_3/ext/openssl/ossl_pkcs7.c branches/ruby_2_3/ext/openssl/ossl_pkey.c branches/ruby_2_3/ext/openssl/ossl_pkey_dh.c branches/ruby_2_3/ext/openssl/ossl_pkey_dsa.c branches/ruby_2_3/ext/openssl/ossl_pkey_ec.c branches/ruby_2_3/ext/openssl/ossl_pkey_rsa.c branches/ruby_2_3/ext/openssl/ossl_ssl_session.c branches/ruby_2_3/ext/openssl/ossl_version.h branches/ruby_2_3/ext/openssl/ossl_x509cert.c branches/ruby_2_3/ext/openssl/ossl_x509crl.c branches/ruby_2_3/ext/openssl/ossl_x509req.c branches/ruby_2_3/test/openssl/test_x509cert.rb branches/ruby_2_3/version.h Index: ruby_2_3/test/openssl/test_x509cert.rb =================================================================== --- ruby_2_3/test/openssl/test_x509cert.rb (revision 62884) +++ ruby_2_3/test/openssl/test_x509cert.rb (revision 62885) @@ -215,6 +215,16 @@ class OpenSSL::TestX509Certificate < Tes https://github.com/ruby/ruby/blob/trunk/ruby_2_3/test/openssl/test_x509cert.rb#L215 assert_equal(true, cert.check_private_key(@rsa2048)) end + def test_read_from_file + cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::SHA1.new) + Tempfile.create("cert") { |f| + f << cert.to_pem + f.rewind + assert_equal cert.to_der, OpenSSL::X509::Certificate.new(f).to_der + } + end + private def certificate_error_returns_false Index: ruby_2_3/version.h =================================================================== --- ruby_2_3/version.h (revision 62884) +++ ruby_2_3/version.h (revision 62885) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/version.h#L1 #define RUBY_VERSION "2.3.7" #define RUBY_RELEASE_DATE "2018-03-22" -#define RUBY_PATCHLEVEL 431 +#define RUBY_PATCHLEVEL 432 #define RUBY_RELEASE_YEAR 2018 #define RUBY_RELEASE_MONTH 3 Index: ruby_2_3/ChangeLog =================================================================== --- ruby_2_3/ChangeLog (revision 62884) +++ ruby_2_3/ChangeLog (revision 62885) @@ -1,3 +1,36 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ChangeLog#L1 +Thu Mar 22 12:28:23 2018 NAKAMURA Usaku <usa@r...> + + merge https://github.com/ruby/openssl/commit/3af2635f117f8da563d180bc1c58702aecb16e0c + patched by Kazuki Yamaguchi <k@r...> + + bio: prevent possible GC issue in ossl_obj2bio() + + Prevent the new object created by StringValue() from being GCed. + Luckily, as none of the callers of ossl_obj2bio() reads from the + returned BIO after possible triggering GC, this has not been a real + problem. + + As a bonus, ossl_protect_obj2bio() function which is no longer used + anywhere is removed. + + merge https://github.com/ruby/openssl/commit/f842b0d5c5e37527c11954a4b7a98c8d9cc57865 + patched by Kazuki Yamaguchi <k@r...> + + bio: do not use the FILE BIO method in ossl_obj2bio() + + Read everything from an IO object into a String first and use the + memory buffer BIO method just as we do for String inputs. + + For MSVC builds, the FILE BIO method uses the "UPLINK" interface that + requires the application to provide OPENSSL_Applink() function. For us, + the "application" means ruby.exe, in which we can't do anything. As a + workaround, avoid using the FILE BIO method at all. + + Usually private keys or X.509 certificates aren't that large and the + temporarily increased memory usage hopefully won't be an issue. + + ext/openssl/ossl_version.h (OpenSSL::VERSION): bump to 1.1.1. + Thu Mar 22 11:24:43 2018 NAKAMURA Usaku <usa@r...> * win32/win32.c (set_pioinfo_extra): use more reliable way to search Index: ruby_2_3/ext/openssl/ossl_pkey_ec.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkey_ec.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkey_ec.c (revision 62885) @@ -188,7 +188,7 @@ static VALUE ossl_ec_key_initialize(int https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_ec.c#L188 ec = EC_KEY_new(); group = arg; } else { - BIO *in = ossl_obj2bio(arg); + BIO *in = ossl_obj2bio(&arg); if (!NIL_P(pass)) { passwd = StringValuePtr(pass); @@ -792,7 +792,7 @@ static VALUE ossl_ec_group_initialize(in https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_ec.c#L792 if ((group = EC_GROUP_dup(arg1_group)) == NULL) ossl_raise(eEC_GROUP, "EC_GROUP_dup"); } else { - BIO *in = ossl_obj2bio(arg1); + BIO *in = ossl_obj2bio(&arg1); group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); if (!group) { @@ -1307,7 +1307,7 @@ static VALUE ossl_ec_point_initialize(in https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_ec.c#L1307 point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx); } else { - BIO *in = ossl_obj2bio(arg1); + BIO *in = ossl_obj2bio(&arg1); /* BUG: finish me */ Index: ruby_2_3/ext/openssl/ossl_pkcs12.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkcs12.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkcs12.c (revision 62885) @@ -159,7 +159,7 @@ ossl_pkcs12_initialize(int argc, VALUE * https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs12.c#L159 if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); d2i_PKCS12_bio(in, &pkcs); DATA_PTR(self) = pkcs; BIO_free(in); Index: ruby_2_3/ext/openssl/ossl_ssl_session.c =================================================================== --- ruby_2_3/ext/openssl/ossl_ssl_session.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_ssl_session.c (revision 62885) @@ -49,7 +49,7 @@ static VALUE ossl_ssl_session_initialize https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_ssl_session.c#L49 if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL) ossl_raise(eSSLSession, "no session available"); } else { - BIO *in = ossl_obj2bio(arg1); + BIO *in = ossl_obj2bio(&arg1); ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL); Index: ruby_2_3/ext/openssl/ossl_x509crl.c =================================================================== --- ruby_2_3/ext/openssl/ossl_x509crl.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_x509crl.c (revision 62885) @@ -115,7 +115,7 @@ ossl_x509crl_initialize(int argc, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_x509crl.c#L115 return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); crl = PEM_read_bio_X509_CRL(in, &x, NULL, NULL); DATA_PTR(self) = x; if (!crl) { Index: ruby_2_3/ext/openssl/ossl_pkey.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkey.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkey.c (revision 62885) @@ -159,7 +159,7 @@ ossl_pkey_new_from_data(int argc, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey.c#L159 rb_scan_args(argc, argv, "11", &data, &pass); - bio = ossl_obj2bio(data); + bio = ossl_obj2bio(&data); if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) { OSSL_BIO_reset(bio); if (!NIL_P(pass)) { Index: ruby_2_3/ext/openssl/ossl_bio.c =================================================================== --- ruby_2_3/ext/openssl/ossl_bio.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_bio.c (revision 62885) @@ -13,48 +13,22 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_bio.c#L13 #endif BIO * -ossl_obj2bio(VALUE obj) +ossl_obj2bio(volatile VALUE *pobj) { + VALUE obj = *pobj; BIO *bio; - if (RB_TYPE_P(obj, T_FILE)) { - rb_io_t *fptr; - FILE *fp; - int fd; - - GetOpenFile(obj, fptr); - rb_io_check_readable(fptr); - if ((fd = rb_cloexec_dup(FPTR_TO_FD(fptr))) < 0){ - rb_sys_fail(0); - } - rb_update_max_fd(fd); - if (!(fp = fdopen(fd, "r"))){ - int e = errno; - close(fd); - rb_syserr_fail(e, 0); - } - if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){ - fclose(fp); - ossl_raise(eOSSLError, NULL); - } - } - else { - StringValue(obj); - bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); - if (!bio) ossl_raise(eOSSLError, NULL); - } + if (RB_TYPE_P(obj, T_FILE)) + obj = rb_funcallv(obj, rb_intern("read"), 0, NULL); + StringValue(obj); + bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj)); + if (!bio) + ossl_raise(eOSSLError, "BIO_new_mem_buf"); + *pobj = obj; return bio; } -BIO * -ossl_protect_obj2bio(VALUE obj, int *status) -{ - BIO *ret = NULL; - ret = (BIO*)rb_protect((VALUE(*)_((VALUE)))ossl_obj2bio, obj, status); - return ret; -} - VALUE ossl_membio2str0(BIO *bio) { Index: ruby_2_3/ext/openssl/ossl_bio.h =================================================================== --- ruby_2_3/ext/openssl/ossl_bio.h (revision 62884) +++ ruby_2_3/ext/openssl/ossl_bio.h (revision 62885) @@ -10,8 +10,7 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_bio.h#L10 #if !defined(_OSSL_BIO_H_) #define _OSSL_BIO_H_ -BIO *ossl_obj2bio(VALUE); -BIO *ossl_protect_obj2bio(VALUE,int*); +BIO *ossl_obj2bio(volatile VALUE *); VALUE ossl_membio2str0(BIO*); VALUE ossl_membio2str(BIO*); VALUE ossl_protect_membio2str(BIO*,int*); Index: ruby_2_3/ext/openssl/ossl_pkey_dh.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkey_dh.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkey_dh.c (revision 62885) @@ -225,7 +225,7 @@ ossl_dh_initialize(int argc, VALUE *argv https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_dh.c#L225 } else { arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); if (!dh){ OSSL_BIO_reset(in); Index: ruby_2_3/ext/openssl/ossl_x509cert.c =================================================================== --- ruby_2_3/ext/openssl/ossl_x509cert.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_x509cert.c (revision 62885) @@ -161,7 +161,7 @@ ossl_x509_initialize(int argc, VALUE *ar https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_x509cert.c#L161 return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); x509 = PEM_read_bio_X509(in, &x, NULL, NULL); DATA_PTR(self) = x; if (!x509) { Index: ruby_2_3/ext/openssl/ossl_pkcs7.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkcs7.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkcs7.c (revision 62885) @@ -193,7 +193,7 @@ ossl_pkcs7_s_read_smime(VALUE klass, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L193 VALUE ret, data; ret = NewPKCS7(cPKCS7); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); out = NULL; pkcs7 = SMIME_read_PKCS7(in, &out); BIO_free(in); @@ -225,7 +225,7 @@ ossl_pkcs7_s_write_smime(int argc, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L225 SafeGetPKCS7(pkcs7, p7); if(!NIL_P(data) && PKCS7_is_detached(p7)) flg |= PKCS7_DETACHED; - in = NIL_P(data) ? NULL : ossl_obj2bio(data); + in = NIL_P(data) ? NULL : ossl_obj2bio(&data); if(!(out = BIO_new(BIO_s_mem()))){ BIO_free(in); ossl_raise(ePKCS7Error, NULL); @@ -262,7 +262,7 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L262 pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ flg = NIL_P(flags) ? 0 : NUM2INT(flags); ret = NewPKCS7(cPKCS7); - in = ossl_obj2bio(data); + in = ossl_obj2bio(&data); if(NIL_P(certs)) x509s = NULL; else{ x509s = ossl_protect_x509_ary2sk(certs, &status); @@ -318,7 +318,7 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *ar https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L318 else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ flg = NIL_P(flags) ? 0 : NUM2INT(flags); ret = NewPKCS7(cPKCS7); - in = ossl_obj2bio(data); + in = ossl_obj2bio(&data); x509s = ossl_protect_x509_ary2sk(certs, &status); if(status){ BIO_free(in); @@ -369,7 +369,7 @@ ossl_pkcs7_initialize(int argc, VALUE *a https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L369 if(rb_scan_args(argc, argv, "01", &arg) == 0) return self; arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL); if (!p7) { OSSL_BIO_reset(in); @@ -760,7 +760,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L760 x509st = GetX509StorePtr(store); flg = NIL_P(flags) ? 0 : NUM2INT(flags); if(NIL_P(indata)) indata = ossl_pkcs7_get_data(self); - in = NIL_P(indata) ? NULL : ossl_obj2bio(indata); + in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata); if(NIL_P(certs)) x509s = NULL; else{ x509s = ossl_protect_x509_ary2sk(certs, &status); @@ -827,7 +827,7 @@ ossl_pkcs7_add_data(VALUE self, VALUE da https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkcs7.c#L827 if(!PKCS7_content_new(pkcs7, NID_pkcs7_data)) ossl_raise(ePKCS7Error, NULL); } - in = ossl_obj2bio(data); + in = ossl_obj2bio(&data); if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err; for(;;){ if((len = BIO_read(in, buf, sizeof(buf))) <= 0) Index: ruby_2_3/ext/openssl/ossl_version.h =================================================================== --- ruby_2_3/ext/openssl/ossl_version.h (revision 62884) +++ ruby_2_3/ext/openssl/ossl_version.h (revision 62885) @@ -10,6 +10,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_version.h#L10 #if !defined(_OSSL_VERSION_H_) #define _OSSL_VERSION_H_ -#define OSSL_VERSION "1.1.0" +#define OSSL_VERSION "1.1.1" #endif /* _OSSL_VERSION_H_ */ Index: ruby_2_3/ext/openssl/ossl_pkey_dsa.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkey_dsa.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkey_dsa.c (revision 62885) @@ -224,7 +224,7 @@ ossl_dsa_initialize(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_dsa.c#L224 else { if (!NIL_P(pass)) passwd = StringValuePtr(pass); arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); if (!dsa) { OSSL_BIO_reset(in); Index: ruby_2_3/ext/openssl/ossl_config.c =================================================================== --- ruby_2_3/ext/openssl/ossl_config.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_config.c (revision 62885) @@ -41,7 +41,7 @@ DupConfigPtr(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_config.c#L41 OSSL_Check_Kind(obj, cConfig); str = rb_funcall(obj, rb_intern("to_s"), 0); - bio = ossl_obj2bio(str); + bio = ossl_obj2bio(&str); conf = NCONF_new(NULL); if(!conf){ BIO_free(bio); Index: ruby_2_3/ext/openssl/ossl_pkey_rsa.c =================================================================== --- ruby_2_3/ext/openssl/ossl_pkey_rsa.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_pkey_rsa.c (revision 62885) @@ -220,7 +220,7 @@ ossl_rsa_initialize(int argc, VALUE *arg https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_pkey_rsa.c#L220 else { if (!NIL_P(pass)) passwd = StringValuePtr(pass); arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); if (!rsa) { OSSL_BIO_reset(in); Index: ruby_2_3/ext/openssl/ossl_x509req.c =================================================================== --- ruby_2_3/ext/openssl/ossl_x509req.c (revision 62884) +++ ruby_2_3/ext/openssl/ossl_x509req.c (revision 62885) @@ -123,7 +123,7 @@ ossl_x509req_initialize(int argc, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_x509req.c#L123 return self; } arg = ossl_to_der_if_possible(arg); - in = ossl_obj2bio(arg); + in = ossl_obj2bio(&arg); req = PEM_read_bio_X509_REQ(in, &x, NULL, NULL); DATA_PTR(self) = x; if (!req) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/