如何解决支持库中发生的分段故障问题?

时间:2013-01-24 10:48:27

标签: c++ c openssl segmentation-fault

我有一个非常奇怪的问题。我可以通过以下小样本代码来复制问题:

#include <openssl/ssl.h>
#include <openssl/err.h>

#include <iostream>

void printSSLErrors()
{
    int l_err = ERR_get_error();
    while(l_err!=0)
    {
      std::cout << "SSL ERROR: " << ERR_error_string(l_err, NULL) << std::endl;
      l_err = ERR_get_error();
    }
}

int main(int argc, char* argv[]) {

    SSL_library_init();
    SSL_load_error_strings();

    // context
    SSL_CTX* mp_ctx;

    if(!(mp_ctx = SSL_CTX_new(SSLv23_server_method())))
    {
      printSSLErrors();
      return 0;
    }

    std::cout << "CTX created OK" << std::endl;

    // set certificate and private key
    if(SSL_CTX_use_certificate_file(mp_ctx, argv[1], SSL_FILETYPE_PEM)!=1)
    {
      printSSLErrors();
      return 0;
    }

    std::cout << "Certificate intialised OK" << std::endl;

    if(SSL_CTX_use_PrivateKey_file(mp_ctx, argv[2], SSL_FILETYPE_PEM)!=1)
    {
      printSSLErrors();
      return 0;
    }

    std::cout << "Key intialised OK" << std::endl;

    SSL_CTX_free(mp_ctx);
    ERR_free_strings();
}

当我编译它并使用-lssl链接它时,此程序按预期工作。但问题是openssl例程是应用程序的一部分,该应用程序也链接在mysqlclient库中。我现在用-lssl -lmysqlclient重新编译上面的代码(请注意,我不在此处包含或使用该库中的任何内容)。如果我再次执行程序,我会在open ssl库中遇到分段错误。我能从gdb中取出的最多是:

[Thread debugging using libthread_db enabled]
[New Thread -1208158528 (LWP 32359)]
CTX created OK
Certificate intialised OK

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1208158528 (LWP 32359)]
0x001b1213 in X509_get_pubkey () from /lib/libcrypto.so.4

(gdb) backtrace
#0  0x001b1213 in X509_get_pubkey () from /lib/libcrypto.so.4
#1  0x00de8a6c in SSL_rstate_string () from /lib/libssl.so.4
#2  0x086f2258 in ?? ()
#3  0xbffceb64 in ?? ()
#4  0x086f1130 in ?? ()
#5  0xbffceaa8 in ?? ()
#6  0x086f2258 in ?? ()
#7  0x086f0d90 in ?? ()
#8  0x00df4858 in ?? () from /lib/libssl.so.4
#9  0x086f2258 in ?? ()
#10 0x086f1130 in ?? ()
#11 0xbffceaa8 in ?? ()
#12 0x00de9d50 in SSL_CTX_use_PrivateKey_file () from /lib/libssl.so.4
Previous frame inner to this frame (corrupt stack?)
(gdb) frame 0
#0  0x001b1213 in X509_get_pubkey () from /lib/libcrypto.so.4

出于某种原因,这种情况只发生在我使用mysqlclient v 15而不是mysqlclient v 16时。这对于任何人来说都可能过于模糊,但是对于如何链接动态库以及代码本身不连接的一些评论使用会导致这些错误会非常有帮助。

系统是:

RHEL ES4,gcc 3.4.6,openssl-0.9.7a,MySQL-5.11

有什么想法吗?

编辑:这是可能更清楚地澄清事情的输出:

[Lieuwe ~]$ c++ openssl_test.cpp -lssl -o ssltest 
[Lieuwe ~]$ ./ssltest /etc/httpd/conf/certs/test.crt /etc/httpd/conf/certs/test.key 
CTX created OK
Certificate intialised OK
Key intialised OK
[Lieuwe ~]$ c++ openssl_test.cpp -lmysqlclient -lssl -o ssltest 
[Lieuwe ~]$ ./ssltest /etc/httpd/conf/certs/test.crt /etc/httpd/conf/certs/test.key 
CTX created OK
Certificate intialised OK
Segmentation fault (core dumped)
[Lieuwe ~]$ 

请注意,为此我使用apache服务器也使用的crt和密钥文件(并且正常工作)

编辑2:这是程序

的valgrind的(相关?)输出
CTX created OK
--5429-- REDIR: 0x5F6C80 (memchr) redirected to 0x4006184 (memchr)
Certificate intialised OK
==5429== Invalid read of size 4
==5429==    at 0xCF4205: X509_get_pubkey (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xDE8A6B: (within /lib/libssl.so.0.9.7a)
==5429==    by 0xDE9D4F: SSL_CTX_use_PrivateKey_file (in /lib/libssl.so.0.9.7a)
==5429==    by 0x8048C77: main (in /home/liwu/ssltest)
==5429==  Address 0x4219940 is 0 bytes inside a block of size 84 free'd
==5429==    at 0x4004EFA: free (vg_replace_malloc.c:235)
==5429==    by 0xC7FD00: CRYPTO_free (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xCE53A7: (within /lib/libcrypto.so.0.9.7a)
==5429==    by 0xCE5562: ASN1_item_free (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xCE0560: X509_free (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xDE979E: SSL_CTX_use_certificate_file (in /lib/libssl.so.0.9.7a)
==5429==    by 0x8048C23: main (in /home/liwu/ssltest)
==5429== 
==5429== Invalid read of size 4
==5429==    at 0xCD4A5F: EVP_PKEY_copy_parameters (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xDE8A7C: (within /lib/libssl.so.0.9.7a)
==5429==    by 0xDE9D4F: SSL_CTX_use_PrivateKey_file (in /lib/libssl.so.0.9.7a)
==5429==    by 0x8048C77: main (in /home/liwu/ssltest)
==5429==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5429== 
==5429== Process terminating with default action of signal 11 (SIGSEGV)
==5429==  Access not within mapped region at address 0x0
==5429==    at 0xCD4A5F: EVP_PKEY_copy_parameters (in /lib/libcrypto.so.0.9.7a)
==5429==    by 0xDE8A7C: (within /lib/libssl.so.0.9.7a)
==5429==    by 0xDE9D4F: SSL_CTX_use_PrivateKey_file (in /lib/libssl.so.0.9.7a)
==5429==    by 0x8048C77: main (in /home/liwu/ssltest)
==5429== 

3 个答案:

答案 0 :(得分:1)

我建议您在Valgrind下运行您的程序。 Valgrind旨在为这类问题提供帮助,它通常比调试器更容易使用。

如果我冒险猜测,我首先会怀疑应用程序中的内存错误(或者,不太可能,在其中一个共享库中)对生成的可执行文件的内存布局敏感。添加一个新的共享库,或者说,启用调试选项可以很好地使问题出现或消失,无明显原因。

答案 1 :(得分:0)

唯一合乎逻辑的解释可能是无法找到X509_get_pubkey()所需的公钥。

您能否确认该功能所要求的公钥是否可用?

答案 2 :(得分:0)

我认为mysql客户端库与另一个版本的libssl链接。如果您使用的是linux:是否通过发行版的官方存储库安装了这两个库?您是否链接到这些库的静态(.a)或动态(.so)版本?

您可以使用nm命令来了解更多信息(请参阅联机帮助页)。

您可以尝试自己重建mysql客户端库,以确保使用相同的libssl版本并查看问题是否消失。