You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by al...@apache.org on 2017/05/27 00:45:55 UTC
kudu git commit: Work around another OpenSSL thread safety bug
Repository: kudu
Updated Branches:
refs/heads/master 1b89ec813 -> d0270172e
Work around another OpenSSL thread safety bug
In the course of debugging some CHECK failures and TSAN errors, I found
that older versions of OpenSSL have non-threadsafe OBJ_create and even
ERR_peek_error methods. This commit fixes an instance where we were
calling OBJ_create concurrently by wrapping it in a std::call_once. I
don't have a fix for ERR_peek_err unsafety, since that's used
pervasively in most methods touching OpenSSL.
Side note: for debugging issues like this, I find it helpful to run ASAN
with the following options:
ASAN_OPTIONS="fast_unwind_on_malloc=0"
That option typically makes races more reproducible, and produces better
stack traces as well.
Change-Id: I9a9fe1a32f77bf24a5c7e692a55b8ad96488d409
Reviewed-on: http://gerrit.cloudera.org:8080/6997
Tested-by: Kudu Jenkins
Reviewed-by: Alexey Serbin <as...@cloudera.com>
Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/d0270172
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/d0270172
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/d0270172
Branch: refs/heads/master
Commit: d0270172e91bf6bcb045cb63a731609472fa6be4
Parents: 1b89ec8
Author: Dan Burkert <da...@apache.org>
Authored: Thu May 25 16:24:17 2017 -0700
Committer: Alexey Serbin <as...@cloudera.com>
Committed: Sat May 27 00:45:13 2017 +0000
----------------------------------------------------------------------
src/kudu/security/cert-test.cc | 24 ++++++++++++++++++++++++
src/kudu/security/cert.cc | 13 +++++++------
2 files changed, 31 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kudu/blob/d0270172/src/kudu/security/cert-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/security/cert-test.cc b/src/kudu/security/cert-test.cc
index 275a60b..acd0f74 100644
--- a/src/kudu/security/cert-test.cc
+++ b/src/kudu/security/cert-test.cc
@@ -15,7 +15,9 @@
// specific language governing permissions and limitations
// under the License.
+#include <thread>
#include <utility>
+#include <vector>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
@@ -25,11 +27,14 @@
#include "kudu/security/crypto.h"
#include "kudu/security/openssl_util.h"
#include "kudu/security/test/test_certs.h"
+#include "kudu/util/barrier.h"
#include "kudu/util/status.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"
using std::pair;
+using std::thread;
+using std::vector;
namespace kudu {
namespace security {
@@ -60,6 +65,25 @@ class CertTest : public KuduTest {
PrivateKey ca_exp_private_key_;
};
+// Regression test to make sure that GetKuduKerberosPrincipalOidNid is thread
+// safe. OpenSSL 1.0.0's OBJ_create method is not thread safe.
+TEST_F(CertTest, GetKuduKerberosPrincipalOidNidConcurrent) {
+ int kConcurrency = 16;
+ Barrier barrier(kConcurrency);
+
+ vector<thread> threads;
+ for (int i = 0; i < kConcurrency; i++) {
+ threads.emplace_back([&] () {
+ barrier.Wait();
+ CHECK_NE(NID_undef, GetKuduKerberosPrincipalOidNid());
+ });
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
+
// Check input/output of the X509 certificates in PEM format.
TEST_F(CertTest, CertInputOutputPEM) {
const Cert& cert = ca_cert_;
http://git-wip-us.apache.org/repos/asf/kudu/blob/d0270172/src/kudu/security/cert.cc
----------------------------------------------------------------------
diff --git a/src/kudu/security/cert.cc b/src/kudu/security/cert.cc
index cde4e47..fa4c753 100644
--- a/src/kudu/security/cert.cc
+++ b/src/kudu/security/cert.cc
@@ -17,6 +17,7 @@
#include "kudu/security/cert.h"
+#include <mutex>
#include <string>
#include <openssl/evp.h>
@@ -57,12 +58,12 @@ string X509NameToString(X509_NAME* name) {
int GetKuduKerberosPrincipalOidNid() {
InitializeOpenSSL();
- SCOPED_OPENSSL_NO_PENDING_ERRORS;
-
- int nid = OBJ_txt2nid(kKuduKerberosPrincipalOidStr);
- if (nid != NID_undef) return nid;
- nid = OBJ_create(kKuduKerberosPrincipalOidStr, "kuduPrinc", "kuduKerberosPrincipal");
- CHECK_NE(nid, NID_undef) << "could not create kuduPrinc oid";
+ static std::once_flag flag;
+ static int nid;
+ std::call_once(flag, [&] () {
+ nid = OBJ_create(kKuduKerberosPrincipalOidStr, "kuduPrinc", "kuduKerberosPrincipal");
+ CHECK_NE(nid, NID_undef) << "failed to create kuduPrinc oid: " << GetOpenSSLErrors();
+ });
return nid;
}