[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