components/openssl/common/patches/029-fork_safe.patch
author Misaki Miyashita <Misaki.Miyashita@Oracle.COM>
Thu, 28 May 2015 09:54:36 -0700
changeset 4370 7043c27399f1
parent 4366 components/openssl/openssl-1.0.1/patches/29_fork_safe.patch@8e8f535e48a5
child 4425 114f035efde7
permissions -rw-r--r--
19375978 Common code between openssl-1.0.1 and openssl-1.0.1-fips-140 should be shared

#
# This file adds the code to setup internal mutexes and callback function.
#	PSARC/2014/077
#	PSARC/2015/043
# This change was implemented in-house.  The issue was brought up to
# the upstream engineers, but there was no commitment.
#
--- openssl-1.0.1f/crypto/cryptlib.c.~1~	Fri Feb  7 10:41:36 2014
+++ openssl-1.0.1f/crypto/cryptlib.c	Thu Feb  6 16:03:58 2014
@@ -116,6 +116,7 @@
 
 #include "cryptlib.h"
 #include <openssl/safestack.h>
+#include <pthread.h>
 
 #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
 static double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */
@@ -184,6 +185,8 @@
  */
 static STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
 
+static pthread_mutex_t *solaris_openssl_locks;
+
 static void (MS_FAR *locking_callback) (int mode, int type,
                                         const char *file, int line) = 0;
 static int (MS_FAR *add_lock_callback) (int *pointer, int amount,
@@ -373,7 +376,10 @@
 void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
                                          (const char *file, int line))
 {
-    dynlock_create_callback = func;
+    /*
+     * we now setup our own dynamic locking callback, and disallow
+     * setting of another locking callback.
+     */
 }

 void CRYPTO_set_dynlock_lock_callback(void (*func) (int mode,
@@ -382,7 +388,10 @@
                                                     const char *file,
                                                     int line))
 {
-    dynlock_lock_callback = func;
+    /*
+     * we now setup our own dynamic locking callback, and disallow
+     * setting of another locking callback.
+     */
 }

 void CRYPTO_set_dynlock_destroy_callback(void (*func)
@@ -389,7 +398,10 @@
                                           (struct CRYPTO_dynlock_value *l,
                                            const char *file, int line))
 {
-    dynlock_destroy_callback = func;
+    /*
+     * we now setup our own dynamic locking callback, and disallow
+     * setting of another locking callback.
+     */
 }

 void (*CRYPTO_get_locking_callback(void)) (int mode, int type,
@@ -402,6 +414,129@@
     return (add_lock_callback);
 }

+/*
+ * This is the locking callback function which all applications will be
+ * using when CRYPTO_lock() is called.
+ */ 
+static void solaris_locking_callback(int mode, int type, const char *file,
+    int line)
+{
+    if (mode & CRYPTO_LOCK) {
+        pthread_mutex_lock(&solaris_openssl_locks[type]);
+    } else {
+        pthread_mutex_unlock(&solaris_openssl_locks[type]);
+    }
+}
+
+
+/*
+ * Implement Solaris's own dynamic locking routines.
+ */
+static struct CRYPTO_dynlock_value *
+solaris_dynlock_create(const char *file, int line)
+{
+    int                        ret;
+    pthread_mutex_t    *dynlock;
+
+    dynlock = OPENSSL_malloc(sizeof(pthread_mutex_t));
+    if (dynlock == NULL) {
+        return (NULL);
+    }
+
+    ret = pthread_mutex_init(dynlock, NULL);
+    OPENSSL_assert(ret);
+
+    return ((struct CRYPTO_dynlock_value *)dynlock);
+}
+
+static void
+solaris_dynlock_lock(int mode, struct CRYPTO_dynlock_valud *dynlock,
+    const char *file, int line)
+{
+    int        ret;
+
+    if (mode & CRYPTO_LOCK) {
+        ret = pthread_mutex_lock((pthread_mutex_t *)dynlock);
+    } else {
+        ret = pthread_mutex_unlock((pthread_mutex_t *)dynlock);
+    }
+
+    OPENSSL_assert(ret == 0);
+}
+
+static void
+solaris_dynlock_destroy(struct CRYPTO_dynlock_value *dynlock,
+    const char *file, int line)
+{
+    int ret;
+    ret = pthread_mutex_destroy((pthread_mutex_t *)dynlock);
+    OPENSSL_assert(ret);
+}
+
+
+/*
+ * This function is called when a child process is forked to setup its own
+ * global locking callback function ptr and mutexes.
+ */
+static void solaris_fork_child(void)
+{
+    /*
+     * clear locking_callback to indicate that locks should
+     * be reinitialized.
+     */
+    locking_callback = NULL;
+    solaris_locking_setup();
+}
+
+/*
+ * This function allocates and initializes the global mutex array, and
+ * sets the locking callback.
+ */
+void solaris_locking_setup()
+{
+    int i;
+    int num_locks;
+
+    /* setup the dynlock callback if not already */
+    if (dynlock_create_callback == NULL) {
+        dynlock_create_callback = solaris_dynlock_create;
+    }
+    if (dynlock_lock_callback == NULL) {
+        dynlock_lock_callback = solaris_dynlock_lock;
+    }
+    if (dynlock_destroy_callback == NULL) {
+        dynlock_destroy_callback = solaris_dynlock_destroy;
+    }
+
+    /* locking callback is already setup. Nothing to do */
+    if (locking_callback != NULL) {
+        return;
+    }
+
+    /*
+     * Set atfork handler so that child can setup its own mutexes and
+     * locking callbacks when it is forked
+     */
+    (void) pthread_atfork(NULL, NULL, solaris_fork_child);
+
+    /* allocate locks needed by OpenSSL  */
+    num_locks = CRYPTO_num_locks();
+    solaris_openssl_locks =
+        OPENSSL_malloc(sizeof (pthread_mutex_t) * num_locks);
+    if (solaris_openssl_locks == NULL) {
+        fprintf(stderr,
+            "solaris_locking_setup: memory allocation failure.\n");
+        abort();
+    }
+
+    /* initialize openssl mutexes */
+    for (i = 0; i < num_locks; i++) {
+        pthread_mutex_init(&solaris_openssl_locks[i], NULL);
+    }
+    locking_callback = solaris_locking_callback;
+
+}
+
 void CRYPTO_set_locking_callback(void (*func) (int mode, int type,
                                                const char *file, int line))
 {
@@ -410,7 +486,11 @@
      * started.
      */
     OPENSSL_init();
-    locking_callback = func;
+
+    /*
+     * we now setup our own locking callback and mutexes, and disallow
+     * setting of another locking callback.
+     */
 }
 
 void CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
@@ -471,9 +551,10 @@
 
 int CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *))
 {
-    if (threadid_callback)
-        return 0;
-    threadid_callback = func;
+    /*
+     * Use the backup method (the address of 'errno') to identify the
+     * thread and disallow setting the threadid callback.
+     */
     return 1;
 }
 
@@ -531,7 +611,10 @@
 
 void CRYPTO_set_id_callback(unsigned long (*func) (void))
 {
-    id_callback = func;
+    /*
+     * Use the backup method to identify the thread/process.
+     * Setting the id callback is disallowed.
+     */
 }
 
 unsigned long CRYPTO_thread_id(void)
--- openssl-1.0.1f/crypto/cryptlib.h.~1~	Fri Feb  7 10:41:42 2014
+++ openssl-1.0.1f/crypto/cryptlib.h	Thu Feb  6 16:04:16 2014
@@ -104,6 +104,8 @@
 void *OPENSSL_stderr(void);
 extern int OPENSSL_NONPIC_relocated;
 
+void solaris_locking_setup();
+
 #ifdef  __cplusplus
 }
 #endif
--- openssl-1.0.1f/crypto/sparccpuid.S.~1~	Fri Feb  7 10:41:37 2014
+++ openssl-1.0.1f/crypto/sparccpuid.S	Thu Feb  6 16:04:14 2014
@@ -398,5 +398,7 @@
 .size	OPENSSL_cleanse,.-OPENSSL_cleanse

 .section	".init",#alloc,#execinstr
+	call	solaris_locking_setup
+	nop
 	call	OPENSSL_cpuid_setup
 	nop
--- openssl-1.0.1f/crypto/x86_64cpuid.pl.~1~	Wed Feb 12 13:20:09 2014
+++ openssl-1.0.1f/crypto/x86_64cpuid.pl	Wed Feb 12 13:21:20 2014
@@ -20,7 +20,10 @@
 print<<___;
 .extern		OPENSSL_cpuid_setup
 .hidden		OPENSSL_cpuid_setup
+.extern		solaris_locking_setup
+.hidden		solaris_locking_setup
 .section	.init
+	call	solaris_locking_setup
 	call	OPENSSL_cpuid_setup
 
 .hidden	OPENSSL_ia32cap_P
--- openssl-1.0.1f/crypto/x86cpuid.pl.~1~	Wed Feb 12 13:38:03 2014
+++ openssl-1.0.1f/crypto/x86cpuid.pl	Wed Feb 12 13:38:31 2014
@@ -353,6 +353,7 @@
 	&ret	();
 &function_end_B("OPENSSL_ia32_rdrand");
 
+&initseg("solaris_locking_setup");
 &initseg("OPENSSL_cpuid_setup");
 
 &asm_finish();