c - Helgrind 报告的 OpenSSL libcrypto.1.0.0 CRYPTO_malloc() 中可能的数据竞争条件

标签 c multithreading openssl

我在使用 Helgrind 测试多线程 (pthreads) 应用程序时遇到问题,报告 libcrypto.1.0.0 中的 CRYPTO_malloc() 内部存在数百个可能的数据竞争。

我已阅读并完全理解所有可用文档,包括《Linux 网络编程权威指南》第 255-259 页和 http://www.openssl.org/docs/crypto/threads.html .

我的代码正在初始化静态和动态锁结构和回调,并注册线程 ID 回调:

CRYPTO_THREADID_set_callback(ssl_mitm_thread_id);
CRYPTO_set_dynlock_create_callback(ssl_mitm_dyn_create_lock);
CRYPTO_set_dynlock_lock_callback(ssl_mitm_dyn_locking_callback);
CRYPTO_set_dynlock_destroy_callback(ssl_mitm_dyn_destroy_lock);
ssl_mitm_lock_mutexes = (pthread_mutex_t*)malloc(CRYPTO_num_locks() *
  sizeof(pthread_mutex_t));
for(i = 0; i < CRYPTO_num_locks(); i++) {
  pthread_mutex_init(&ssl_mitm_lock_mutexes[i], NULL);
}
CRYPTO_set_locking_callback(ssl_mitm_locking_callback);

SSL_library_init();
SSL_load_error_strings();
...etc...

我在锁定回调函数中添加了调试语句,而 openSSL 只是调用了贬值的 CRYPTO_set_locking_callback(),并没有使用新的动态锁定接口(interface)。

即便如此,它还是在调用旧的静态锁定函数,因此也在尝试线程同步,但 Helgrind 仍然认为存在很多可能的数据竞争。大多数(如果不是全部)都在 CRYPTO_malloc() 中。

那么,这个 Helgrind 是过分狂热了还是 OpenSSL/libcrypto 中的错误?

例如

==20093== ----------------------------------------------------------------
==20093==
==20093== Possible data race during write of size 4 at 0x63BA368 by thread #3
==20093== Locks held: none
==20093==    at 0x604F0FE: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==20093==    by 0x57F4186: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093==    by 0x57D20C4: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093==    by 0x57D62E1: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093==    by 0x57DF0B6: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
[snip] (SSL_connect() called)
==20093==
==20093== This conflicts with a previous write of size 4 by thread #6
==20093== Locks held: none
==20093==    at 0x604F0FE: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==20093==    by 0x57E1673: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093==    by 0x57DF359: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
[snip] (SSL_connect() called)
==20093==
==20093== ----------------------------------------------------------------

从 SSL_read、SSL_write、SSL_connect 和 SSL_accept 等调用的 CRYPTO_malloc() 中还有其他数据竞争示例。

最佳答案

下面片段中的最后一行是 Helgrind 提示的代码行:

void *CRYPTO_malloc(int num, const char *file, int line)
        {
        void *ret = NULL;

        if (num <= 0) return NULL;

        allow_customize = 0;

allow_customize 全局变量在静态初始化中被初始化为1。此值用于确保在调用分配例程本身后不会调用 malloc 自定义函数(CRYPTO_set_mem... 和变体)。此设置为值 0 是在锁之外完成的。从技术上讲,如果一个线程试图调用 CRYPTO_...alloc 函数而另一个线程试图为 CRYPTO 设置自定义函数,则会出现竞争条件,但这可以是被视为应用程序错误。

关于c - Helgrind 报告的 OpenSSL libcrypto.1.0.0 CRYPTO_malloc() 中可能的数据竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22578551/

相关文章:

c - 在c中使用ARM MCU保存数据

c# - Firebase 使任务仅在主线程上执行,导致 Unity 卡住

c# - 晚上 10 点后抛出 System.OutOfMemoryException。我无法捕捉到实际的错误

c++ - Android NDK r8 的 Openssl 构建问题

c - 长度大于8192的base64解码文件?

c - C 中的 Malloc 问题

c - 如何编写模块化网络代码?

c++ - 只有条件为 1 的程序不进入 while 循环

c++ - C++中线程函数参数的问题

java - 从 Android 中的 x.509 证书中获取 CA 详细信息