[Forensics-changes] [yara] 63/368: Fix crash in libcrypto when multithreaded.

Hilko Bengen bengen at moszumanska.debian.org
Sat Jul 1 10:30:11 UTC 2017


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag v3.5.0
in repository yara.

commit ff39967e55b8ee2af1d897db14bf059a7d7f9142
Author: Wesley Shields <wxs at atarininja.org>
Date:   Tue Sep 22 08:23:19 2015 -0400

    Fix crash in libcrypto when multithreaded.
    
    When running multi-threaded you must properly initalize OpenSSL for
    threads. This is done by providing an array of mutexes that is at least
    CRYPTO_num_locks(3) long. You then provide a callback using
    CRYPTO_set_locking_callback(3) which OpenSSL will call as necessary.
    This locking function will either lock or unlock a mutex from the array
    based upon a flag provided. You also need to provide a callback for
    OpenSSL to use to get the current thread id, which it uses to determine
    which lock to operate on.
    
    Failure to do this was causing crashes which would only appear in
    multi-threaded runs, and only when doing things involving libcrypto. The
    crash is most easily triggered by running a bunch of signed PE binaries
    through.
    
    The crash always looked like this:
    
    *** error for object 0x7f983140afc8: incorrect checksum for freed object
    - object was probably modified after being freed.
    
    Thread 2 Crashed:
    0   libsystem_kernel.dylib          0x00007fff8efde286 __pthread_kill + 10
    1   libsystem_c.dylib               0x00007fff874519b3 abort + 129
    2   libsystem_malloc.dylib          0x00007fff955c41cb free + 428
    3   libcrypto.0.9.8.dylib           0x00007fff92e88e45 CRYPTO_free + 37
    4   libcrypto.0.9.8.dylib           0x00007fff92ee0af3 ERR_get_state + 579
    5   libcrypto.0.9.8.dylib           0x00007fff92ebf85c ERR_clear_error + 12
    6   libcrypto.0.9.8.dylib           0x00007fff92e4e3f8 asn1_d2i_read_bio + 56
    7   libcrypto.0.9.8.dylib           0x00007fff92e4e74c ASN1_item_d2i_bio + 44
    8   yara                            0x000000010895f2ed pe_parse_certificates + 333
    9   yara                            0x0000000108962b49 pe__load + 2233
    10  yara                            0x000000010897ab5a yr_modules_load + 266
    11  yara                            0x00000001089712ac yr_execute_code + 3564
    12  yara                            0x00000001089856f9 yr_rules_scan_mem_blocks + 1161
    13  yara                            0x0000000108985af1 yr_rules_scan_file + 113
    14  yara                            0x000000010895a042 scanning_thread + 274
    15  libsystem_pthread.dylib         0x00007fff8c3e405a _pthread_body + 131
    16  libsystem_pthread.dylib         0x00007fff8c3e3fd7 _pthread_start + 176
    17  libsystem_pthread.dylib         0x00007fff8c3e13ed thread_start + 13
    
    When the crash happened there would usually be at least one other thread
    deep within the OpenSSL internals, usually (but not always) in the same
    ASN1_item_d2i_bio() chain.
---
 libyara/libyara.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/libyara/libyara.c b/libyara/libyara.c
index 6d20ad0..30b0a7d 100644
--- a/libyara/libyara.c
+++ b/libyara/libyara.c
@@ -23,6 +23,10 @@ limitations under the License.
 #include <yara/modules.h>
 #include <yara/mem.h>
 
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/crypto.h>
+#endif
+
 #ifdef _WIN32
 #define snprintf _snprintf
 #endif
@@ -42,6 +46,23 @@ pthread_key_t recovery_state_key;
 char lowercase[256];
 char altercase[256];
 
+#ifdef HAVE_LIBCRYPTO
+pthread_mutex_t *locks;
+
+unsigned long pthreads_thread_id(void)
+{
+  return (unsigned long) pthread_self();
+}
+
+void locking_function(int mode, int n, const char *file, int line)
+{
+  if (mode & CRYPTO_LOCK)
+    pthread_mutex_lock(&locks[n]);
+  else
+    pthread_mutex_unlock(&locks[n]);
+}
+#endif
+
 //
 // yr_initialize
 //
@@ -75,6 +96,16 @@ YR_API int yr_initialize(void)
   pthread_key_create(&recovery_state_key, NULL);
   #endif
 
+  #ifdef HAVE_LIBCRYPTO
+  locks = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+  for (i = 0; i < CRYPTO_num_locks(); i++)
+    pthread_mutex_init(&locks[i], NULL);
+
+  // XXX ifdef CRYPTO
+  CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
+  CRYPTO_set_locking_callback(locking_function);
+  #endif
+
   FAIL_ON_ERROR(yr_re_initialize());
   FAIL_ON_ERROR(yr_modules_initialize());
 
@@ -106,6 +137,13 @@ YR_API int yr_finalize(void)
 {
   yr_re_finalize_thread();
 
+  #ifdef HAVE_LIBCRYPTO
+  int i;
+  for (i = 0; i < CRYPTO_num_locks(); i ++)
+    pthread_mutex_destroy(&locks[i]);
+  OPENSSL_free(locks);
+  #endif
+
   #ifdef _WIN32
   TlsFree(tidx_key);
   TlsFree(recovery_state_key);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list