Remove to add openssl locking function on client 84/104984/1
authorKyungwook Tak <k.tak@samsung.com>
Thu, 15 Dec 2016 04:19:28 +0000 (13:19 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Thu, 15 Dec 2016 04:21:15 +0000 (13:21 +0900)
To add locking function in client library side is dangerous of occuring
segmentation fault because it can be used in some dynamic loaded
plugins. If multiple plugins are adding locking function, there is race
condition issue that symbol is unloaded out from the plugin so it makes
segmentation fault.

Change-Id: I1ac443c5d2e166cf05c65b3d937dae64472c713b
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
src/manager/common/crypto-init.cpp
src/manager/common/crypto-init.h

index 9982299..573a4d6 100644 (file)
@@ -81,33 +81,18 @@ void opensslUninstallLocks()
        g_mutexes = NULL;
 }
 
-} // namespace anonymous
-
-
-void initOpenSsl()
+void initOpenSsl(bool isLib)
 {
-       // Loads all error strings (crypto and ssl)
-       SSL_load_error_strings();
-
        /*
         * Initialize libcrypto (add all algorithms, digests & ciphers)
         * It also does the stuff from SSL_library_init() except for ssl_load_ciphers()
         */
        OpenSSL_add_all_algorithms(); // Can be optimized by using EVP_add_cipher instead
 
-       /*
-        *  Initialize libssl (OCSP uses it)
-        *  SSL_library_init() == OpenSSL_add_ssl_algorithms()
-        *  It always returns 1
-        */
-       SSL_library_init();
-
-       // load default configuration (/etc/ssl/openssl.cnf)
-       OPENSSL_config(NULL);
+       if (isLib)
+               return;
 
-       // enable FIPS mode by default
-       if (0 == FIPS_mode_set(1))
-               LogWarning("Failed to set FIPS mode. Key-manager will be operated in non FIPS mode.");
+       // below initializes only for executable client. (key-manager daemon)
 
        /*
         * Initialize entropy
@@ -128,26 +113,22 @@ void initOpenSsl()
                        LogError("Error in U_RAND_file_load");
        }
 
-       // Install locks for multithreading support
-       opensslInstallLocks();
-}
+       /*
+        *  Initialize libssl (OCSP uses it)
+        *  SSL_library_init() == OpenSSL_add_ssl_algorithms()
+        *  It always returns 1
+        */
+       SSL_library_init();
 
-void deinitOpenSsl()
-{
-       opensslUninstallLocks();
-       CONF_modules_unload(1);
-       EVP_cleanup();
-       ERR_free_strings();
-       deinitOpenSslThread();
-}
+       // load default configuration (/etc/ssl/openssl.cnf)
+       OPENSSL_config(NULL);
+       // Loads all error strings (crypto and ssl)
+       SSL_load_error_strings();
 
-void deinitOpenSslThread()
-{
-       CRYPTO_cleanup_all_ex_data();
-       ERR_remove_thread_state(NULL);
+       // Install locks for multithreading support
+       opensslInstallLocks();
 }
 
-namespace {
 std::mutex cryptoInitMutex;
 
 void initOpenSslAndDetach();
@@ -159,22 +140,24 @@ std::atomic<initFnPtr> initFn(&initOpenSslAndDetach);
 
 void initEmpty() {}
 
+// this function will be called only once by initOpenSslOnce for library client
 void initOpenSslAndDetach()
 {
        // DCLP
        std::lock_guard<std::mutex> lock(cryptoInitMutex);
 
        /*
-        * We don't care about memory ordering here. Current thread will order it correctly and for
-        * other threads only store matters. Also only one thread can be here at once because of lock.
+        * We don't care about memory ordering here. Current thread will order it
+        * correctly and for other threads only store matters. Also only one thread
+        * can be here at once because of lock.
         */
        if (initFn.load(std::memory_order_relaxed) != &initEmpty) {
-               initOpenSsl();
+               initOpenSsl(true);
 
                /*
-                * Synchronizes with load. Everything that happened before this store in this thread is
-                * visible to everything that happens after load in another thread. We switch to an empty
-                * function here.
+                * Synchronizes with load. Everything that happened before this store in
+                * this thread is visible to everything that happens after load in another
+                * thread. We switch to an empty function here.
                 */
                initFn.store(&initEmpty, std::memory_order_release);
        }
@@ -182,13 +165,33 @@ void initOpenSslAndDetach()
 
 } // namespace anonymous
 
+void initOpenSsl()
+{
+       initOpenSsl(false);
+}
+
+void deinitOpenSsl()
+{
+       opensslUninstallLocks();
+       CONF_modules_free(); // cleanup of OPENSSL_config
+       EVP_cleanup(); // cleanup of OpenSSL_add_all_algorithms
+       ERR_free_strings(); //cleanup of SSL_load_error_strings
+       deinitOpenSslThread();
+}
+
+void deinitOpenSslThread()
+{
+       CRYPTO_cleanup_all_ex_data();
+       ERR_remove_thread_state(NULL);
+}
+
 void initOpenSslOnce()
 {
        /*
-        * Synchronizes with store. Everything that happened before store in another thread will be
-        * visible in this thread after load.
+        * Synchronizes with store. Everything that happened before store in another
+        * thread will be visible in this thread after load.
         */
        initFn.load(std::memory_order_acquire)();
 }
 
-} /* namespace CKM */
+} // namespace CKM
index e2419b1..d8abeca 100644 (file)
 #include <symbol-visibility.h>
 
 namespace CKM {
+// Remarks!
+//   These functions are used carefully depending on library / executable client.
+//
+//   Init/deinit locking functions are only available for executable client
+//     (it's key-manager daemon)
+//
+//   For library client, locking functions are not supported because it can make
+//   undefined behavior(usually segmentation fault) when the client is used as
+//   plugin(dynamic loaded) because there's probability of openssl's locking function
+//   being init/deinit on multiple plugins.
 
+// Must be called once manually because it'll handle openssl locking functions.
+// Only for server.
 COMMON_API void initOpenSsl();
 COMMON_API void deinitOpenSsl();
+// deinit for every service thread on server.
 COMMON_API void deinitOpenSslThread();
+
+// init for client or common libraries.
+// It'll only do OpenSSL_add_all_algorithms
 COMMON_API void initOpenSslOnce();
 
 } // namespace CKM
-