# # 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.2m/crypto/cryptlib.c.~1~ 2017-11-02 17:32:57.000000000 +0000 +++ openssl-1.0.2m/crypto/cryptlib.c 2017-11-03 09:16:20.891838573 +0000 @@ -116,6 +116,7 @@ #include "cryptlib.h" #include +#include #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,14 +388,20 @@ 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) (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,128 @@ 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_value *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 +544,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, @@ -475,12 +613,10 @@ int CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *)) { - if (threadid_callback) - return 0; - threadid_callback = func; -#ifdef OPENSSL_FIPS - FIPS_crypto_threadid_set_callback(func); -#endif + /* + * Use the backup method (the address of 'errno') to identify the + * thread and disallow setting the threadid callback. + */ return 1; } @@ -536,7 +672,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 @@ -525,5 +525,7 @@ .size _sparcv9_vis1_instrument_bus2,.-_sparcv9_vis1_instrument_bus2 .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 @@ -379,8 +379,10 @@ &ret (); &function_end_B("OPENSSL_ia32_rdseed"); +&initseg("solaris_locking_setup"); &initseg("OPENSSL_cpuid_setup"); +&hidden("solaris_locking_setup"); &hidden("OPENSSL_cpuid_setup"); &hidden("OPENSSL_ia32cap_P");