代码之家  ›  专栏  ›  技术社区  ›  Community wiki

使用自定义openssl版本编译python时的核心转储

  •  9
  • Community wiki  · 技术社区  · 2 年前

    当使用本地openssl-1.0.1f共享安装编译python-3.0rc3时, make 打印没有错误,但我在makeinstall或maketest上得到以下核心转储:

    Program terminated with signal 11, Segmentation fault.
    (gdb) bt
    #0  0x00007f131dd10510 in EVP_PKEY_CTX_dup () from /data2/soft/openssl/lib/libcrypto.so.1.0.0
    #1  0x00007f131dd0284f in EVP_MD_CTX_copy_ex () from /data2/soft/openssl/lib/libcrypto.so.1.0.0
    #2  0x00007f131e256ab5 in EVPnew (name_obj=0x7f131e46a500, digest=0x0, initial_ctx=0x7f131e459a40, cp=0x0, len=0) at /data2/soft/python3/Python-3.4.0rc3/Modules/_hashopenssl.c:410
    #3  0x00007f131e25726e in EVP_new_md5 (self=<value optimized out>, args=<value optimized out>) at /data2/soft/python3/Python-3.4.0rc3/Modules/_hashopenssl.c:799
    #4  0x00000000004c7eef in ?? ()
    

    以下是使用的命令的完整列表

    tar -axf Python-3.4.0rc3.tgz
    cd Python-3*
    # For lzma and a pip-compatible openssl
    export CFLAGS='-I/data2/soft/openssl/include/openssl -I/data2/local/include/'
    export LDFLAGS='-L/data2/soft/openssl/lib -L/data2/local/lib/'
    export LD_LIBRARY_PATH="/data2/soft/openssl/lib:/data2/local/lib/:$LD_LIBRARY_PATH"
    # Ready !
    ./configure --prefix=/data2/soft/python3
    make
    make install
    

    笔记:

    • 操作系统为SUSE Linux Enterprise Server 11(x86_64)
    • 将python指向位于
    • openssl是用 ./config shared --openssldir=/data2/soft/openssl
    • 开放ssl make test 印刷品 所有测试均成功。
    • 如果没有自定义的openssl*FLAGS,make安装将成功,我将获得以下make测试结果: 71 tests OK. tests failed: test_cmd_line test_gdb test_smtpnet test_ssl

    我怎样才能解决这个问题,或者至少调查一下到底发生了什么?

    编辑1-5:

    正确生成了共享库:

    > ls /data2/soft/openssl/lib
    drwxr-xr-x engines
    -rw-r--r-- libcrypto.a
    lrwxrwxrwx libcrypto.so -> libcrypto.so.1.0.0
    -r-xr-xr-x libcrypto.so.1.0.0
    -rw-r--r-- libssl.a
    lrwxrwxrwx libssl.so -> libssl.so.1.0.0
    -r-xr-xr-x libssl.so.1.0.0
    drwxr-xr-x pkgconfig
    

    所以我在安装程序中更改了此设置:

    SSL=/data2/soft/openssl/
    _ssl _ssl.c \                               
        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
        $(SSL)/lib/libssl.a $(SSL)/lib/libcrypto.a -ldl
    

    我相应地改回了LDFLAGS/CFLAGS。但当我运行make clean&&make,因为_hashopen模块:

    gcc -pthread -shared -L/data2/local/lib/ -L/data2/local/lib/ -L/data2/local/lib/ -I/data2/local/include/ build/temp.linux-x86_64-3.4/data2/soft/python3/Python-3.4.0rc3/Modules/_hashopenssl.o -L/data2/local/lib/ -L/usr/local/lib -lssl -lcrypto -o build/lib.linux-x86_64-3.4/_hashlib.cpython-34m.so
    

    我想这是导致核心的原因,因为它们仍然在那里。。。我尝试将类似的内容添加到安装文件中,但此文件没有注释项,创建它会导致另一个更神秘的失败:

    gcc -pthread   -Xlinker -export-dynamic -o python Modules/python.o libpython3.4m.a -lpthread -ldl  -lutil /data2/eoubrayrie/soft/openssl/lib/libssl.a /data2/eoubrayrie/soft/openssl/lib/libcrypto.a -ldl   /data2/eoubrayrie/soft/openssl/lib/libssl.a /data2/eoubrayrie/soft/openssl/lib/libcrypto.a -ldl   -lm  
    libpython3.4m.a(config.o):(.data+0x158): undefined reference to `PyInit__hashopenssl'
    collect2: ld returned 1 exit status
    

    编辑6:

    • 无论如何,我都无法修改_hashlib.so的生成方式,因为Makefile魔法太多了(它不会出现在任何地方,'-lssl'也不会神奇地同时出现在同一行
    • 但我可以通过旧的-I/-L将其动态链接到我自己的openssl:

      ldd build/lib.linux-x86_64-3.4/_hashlib.cpython-34m.so libssl.so.1.0.0 => /data2/soft/openssl/lib/libssl.so.1.0.0 (0x00007f5605799000) libcrypto.so.1.0.0 => /data2/soft/openssl/lib/libcrypto.so.1.0.0 (0x00007f56053bd000)

    • 现在唯一的问题是,gdb info shared 告诉我还有一个是在核心时间使用的。。。但如何?

      From To Syms Read Shared Object Library 0x00007ffff5465930 0x00007ffff5466e98 Yes /data2/soft/python3/Python-3.4.0rc3/build/lib.linux-x86_64-3.4/_hashlib.cpython-34m.so 0x00007ffff5321220 0x00007ffff5351878 Yes /opt/python-2.6-64/lib/libssl.so.1.0.0 0x00007ffff50d3100 0x00007ffff519b118 Yes /opt/python-2.6-64/lib/libcrypto.so.1.0.0

      • env | grep -F 'python-2.6-64' ->什么都没有!
      • grep -RF 'python-2.6-64' /etc/ld.so.* ->同上
      • gcc -print-search-dirs | sed 's/:/\n/g' | grep python ->同上
      • find . -name '*.so*' | xargs ldd | grep ssl ->只给我好的
      • 级别1依赖项也不需要任何错误的ssl版本。已通过以下方式进行检查:
        find . -name '*.so*' | xargs ldd | awk '/\t+[[:alnum:].]+ => [[:alnum:]./]+ \(/ {print $3}' | sort | uniq | xargs ldd | grep ssl
      • strace ./python ./Tools/scripts/run_tests.py 2>&1 | grep python-2.6-64 ->没有显示任何内容

    那么 ld 如果他不知道,就选错了图书馆??它不在任何标准位置(如果它在/lib中,我可以理解…)

    解决方案:

    了解如何静态链接_hashlib this OpenOffice bug :尽管 -Wl,--exclude-libs=ALL" 选项也不起作用,它指向setup.py中正确的行。

    TL;DR这是 patch to setup.py 我申请了。

    最后。。。它起作用了!

    @noloader我接受你最完整的答案,因为你的帮助是无价的,尽管对于任何遇到这个问题的人来说,“确切”的答案是使用上面的补丁进行编译。

    7 回复  |  直到 11 年前
        1
  •  4
  •   jww avp    11 年前
    How can I fix this, or at least investigate what is going on ?
    ...
    export LDFLAGS='-L/data2/soft/openssl/lib -L/data2/local/lib/'
    export LD_LIBRARY_PATH="/data2/soft/openssl/lib:/data2/local/lib/
    

    我也经常遇到这些问题,因为我避免了Debian、Ubuntu、Fedora等提供的OpenSSL的残缺版本。例如,Ubuntu提供了一个禁用TLSv1.1和TLS v1.2的OpenSSL(参见。, Ubuntu 12.04 LTS: OpenSSL downlevel version and does not support TLS 1.2 ).

    您可能加载了错误版本的OpenSSL库。如果可以在调试器下获取错误程序,请发出 info shared 看看哪个 libcrypto libssl 您实际上正在加载。

    ldd 可能也有帮助。在Pyhton可执行文件上运行它: ldd /data2/soft/python3/python 。我只能说它“可能”有帮助,因为OpenSSL是二进制兼容的, libcrypto.so.1.0.0 (使用 otool -L 在Mac OS X上)。下面我使用了 rpath 强制链接中的库 /usr/local/ssl/lib/ .

    $ ldd my-test.exe 
        linux-vdso.so.1 =>  (0x00007fffd61ff000)
        libssl.so.1.0.0 => /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f151528e000)
        libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f1514e74000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1514c42000)
        ...
    

    作为解决方案,您可以尝试添加 rpath公司 :

    LDFLAGS='-L/data2/soft/openssl/lib -L/data2/local/lib/ -Wl,-rpath,/data2/soft/openssl/lib'
    

    更好的修复方法是链接到OpenSSL库的静态版本,以避免这些问题。我相信你可以做到这一点: -Bstatic -lssl -lcrypto -Bdynamic -ldl .

    就我个人而言,我甚至不使用 -Bstatic 因为不同的一次性问题。我打开Makefile,删除 -lssl -lcrypto ,并向存档添加完整路径以消除所有歧义。例如 /data2/soft/openssl/lib/libssl.a /data2/soft/openssl/lib/libcrypto.a .

    注水井 :一个 rpath公司 在Mac OS X上不受支持。因为链接器不受支持,所以Mac OS X需要采取更极端的措施 -B静态 任何一个你必须使用完整路径技巧。


    openssl was built with ./config shared --openssldir=/data2/soft/openssl
    

    还有一件事在Fedora上,仅指定 shared 。您还需要添加以下内容:

    export CFLAGS="-fPIC"
    

    否则,不会生成共享对象。如果没有构建1.0.1f共享对象,您可能会得到发行版提供的下层版本。你可以检查建造了什么 之前 安装方式:

    ./config shared --openssldir=/data2/soft/openssl
    make all
    
    # Verify artifacts
    find . -iname -libcrypto.*
    find . -iname -libssl.*
    
    # Proceed if OK
    sudo make install
    

    最后,确保 全部的 Python的依赖项也使用您的OpenSSL版本,而不是系统的OpenSSL。

    我最近在我的程序使用OpenSSL时遇到了这个问题;但我的程序也使用了 libevent libevent事件 使用了系统版本的OpenSSL。我通过重建修复了它 libevent事件 并强制它静态链接到我的OpenSSL版本。

        2
  •  3
  •   jww avp    11 年前

    我该如何改变它?将添加一个_ssl.c:gcc。。。行覆盖默认行为?我的Makefile技能生锈了,这只野兽有1600多行!!

    以下是您要查看的文件:

    $ cd Python-3.4.0rc3
    
    $ grep -R -- '-lcrypto' *
    Modules/Setup.dist:#    -L$(SSL)/lib -lssl -lcrypto
    
    $ grep -R -- '-lssl' *
    Modules/Setup.dist:#    -L$(SSL)/lib -lssl -lcrypto
    

    以下是 Setup.dist :

    # Socket module helper for SSL support; you must comment out the other
    # socket line above, and possibly edit the SSL variable:
    #SSL=/usr/local/ssl
    #_ssl _ssl.c \
    #   -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
    #   -L$(SSL)/lib -lssl -lcrypto
    

    取消注释行并更改 设置列表 如下所示。我将OpenSSL保存在 /usr/local/ssl ,所以下面就是我的设置方式(您应该使用 /data2/soft/openssl/lib/... ):

    SSL=/usr/local/ssl
    _ssl _ssl.c \
        -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
        /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a -ldl
    

    使用 满的 存档的路径,不要使用 -l 。请务必添加 -ldl 因为OpenSSL在此配置中需要它。

    一旦你改变了 设置列表 ,重新运行 ./configure 以实现更改。


    将上述行更改为后 configure :

    $ grep -R "libssl.a" *
    Makefile:LOCALMODLIBS=  /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a -ldl 
    Makefile:Modules/_ssl$(SO):  Modules/_ssl.o; $(BLDSHARED)  Modules/_ssl.o  /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a -ldl  -o Modules/_ssl$(SO)
    Modules/Setup: /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a -ldl 
    Modules/Setup.dist: /usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a -ldl 
    

    您可以使用 ldd otool -L 。你会的 请参见OpenSSL依赖项。之后 make 嗯,这是我得到的:

    $ find . -iname python
    ./python
    $ ldd ./python
        linux-vdso.so.1 =>  (0x00007fff67709000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3aed8e1000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3aed6dd000)
        libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f3aed4d9000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3aed257000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3aececc000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3aedb14000)
    

    libssl libcrypto 依赖项出错:)和 make test 运行良好(实际上,一个测试因Python错误而失败: Issue 20896 ):

    ======================================================================
    ERROR: test_get_server_certificate (test.test_ssl.NetworkedTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/jwalton/Python-3.4.0rc3/Lib/test/test_ssl.py", line 1373, in test_get_server_certificate
        _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
      File "/home/jwalton/Python-3.4.0rc3/Lib/test/test_ssl.py", line 1354, in _test_get_server_certificate
        pem = ssl.get_server_certificate((host, port))
      File "/home/jwalton/Python-3.4.0rc3/Lib/ssl.py", line 902, in get_server_certificate
        with context.wrap_socket(sock) as sslsock:
      File "/home/jwalton/Python-3.4.0rc3/Lib/ssl.py", line 344, in wrap_socket
        _context=self)
      File "/home/jwalton/Python-3.4.0rc3/Lib/ssl.py", line 540, in __init__
        self.do_handshake()
      File "/home/jwalton/Python-3.4.0rc3/Lib/ssl.py", line 767, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:598)
    
    ----------------------------------------------------------------------
    Ran 96 tests in 8.610s
    
    FAILED (errors=1, skipped=3)
    test test_ssl failed
    make: *** [test] Error 1
    
        3
  •  1
  •   jww avp    11 年前

    这不是答案,只是与你一起跑步后的观察:

    $ make 
    ...
    
    gcc -pthread -c -Wno-unused-result -Werror=declaration-after-statement
      -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I. -IInclude -I./Include
      -DPy_BUILD_CORE -o Objects/capsule.o Objects/capsule.c
    

    -fwrapv 真的很糟糕。它用于使非法程序工作。最好修复损坏的程序并删除 -fwrapv公司 。参见Ian Lance Taylor的博客 Signed Overflow .

        4
  •  0
  •   jww avp    11 年前

    无论如何,我都无法修改_hashlib.so的生成方式,因为Makefile魔法太多了(它不会出现在任何地方,'-lssl'也不会神奇地同时出现在同一行

    grep 是你的朋友;)

    $ grep -R _hashlib * | grep ssl
    Lib/hashlib.py:        f = getattr(_hashlib, 'openssl_' + name)
    Lib/hashlib.py:            _hashlib.openssl_md_meth_names)
    Lib/test/test_hashlib.py:            self.assertTrue(hasattr(_hashlib, 'openssl_md5'))
    Lib/test/test_hashlib.py:            self.assertTrue(hasattr(_hashlib, 'openssl_sha1'))
    Lib/test/test_hashlib.py:                constructor = getattr(_hashlib, 'openssl_'+algorithm, None)
    Lib/test/ssltests.py:TESTS = ['test_asyncio', 'test_ftplib', 'test_hashlib', 'test_httplib',
    Lib/test/time_hashlib.py:    print(" '_hashlib' 'openssl_hName' 'fast' tests the builtin _hashlib")
    Modules/_hashopenssl.c:    "_hashlib.HASH",    /*tp_name*/
    Modules/_hashopenssl.c:static struct PyModuleDef _hashlibmodule = {
    Modules/_hashopenssl.c:    "_hashlib",
    Modules/_hashopenssl.c:PyInit__hashlib(void)
    Modules/_hashopenssl.c:    m = PyModule_Create(&_hashlibmodule);
    PCbuild/build_ssl.py:# Script for building the _ssl and _hashlib modules for Windows.
    PCbuild/build_ssl.py:# for the actual _ssl.pyd and _hashlib.pyd DLLs.
    PCbuild/build_ssl.py:# it should configure and build SSL, then build the _ssl and _hashlib
    setup.py:                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
    setup.py:                print("warning: openssl 0x%08x is too old for _hashlib" %
    Tools/ssl/test_multiple_versions.py:    "test_asyncio", "test_ftplib", "test_hashlib", "test_httplib",
    Tools/ssl/test_multiple_versions.py:MINIMAL_TESTS = ["test_ssl", "test_hashlib"]
    
        5
  •  0
  •   jww avp    11 年前

    另一个部分答案。。。

    但我可以通过旧的-I/-L将其动态链接到我自己的openssl:

    ...

    现在唯一的问题是,共享的gdb信息仍然告诉我另一个信息是在核心时间使用的。。。但如何?

    那是你的好老朋友 -l -L . 不要使用它们 因为他们一直都在做这种事情(从一个过去受过这种折磨的人身上)。而是指定 满的 到的路径 libssl libcrypto 。例如,使用 /data2/soft/openssl/lib/libssl.a .

        6
  •  0
  •   Pavel Machyniak    11 年前

    我们也遇到了类似的问题。我们正在使用 apache httpd + mod_wsgi + python + django 以及我们的c++模块 apache httpd 它还使用 openssl 。现在所有内容都加载到一个 httpd 过程中,使用我们的c++模块加载了openssl共享库的正确版本(1.0.0l)。但一旦我们访问网络,python就会加载 hashlib 同样的问题出现在从python调用的openssl中segfault。

    通常,python使用 开放ssl 可在 默认位置 没有办法在不干扰的情况下指定它 setup.py 或生成文件。Python开发人员应添加配置设置 --with_ssl=path .

    我们安装了新的openssl-libs并重建了python和其他二进制文件,但没有成功。我们将默认的libssl.so和libcrypto.so映射到新的openssl二进制文件,但没有成功。最后,在阅读了这个线程之后,我意识到在编译python时可能使用了错误的头。这就是问题所在。按照以下步骤解决问题:

    • 不能有不正确的版本 开放ssl 中的标头 /usr/include 和默认位置 /usr/local/ssl , /usr/contrib/ssl (如果已安装 openssl-devel 然后卸载它,或者干脆擦除/重命名目录)

    yum remove openssl-devel

    • 从中创建openssl安装的符号链接 /usr/local/ssl

    ln -s /opt/openssl-1.0.1l /usr/local/ssl

    • 确保可以从 /usr/lib (如果此处未安装,请进行符号链接)

    ln -s /opt/openssl-1.0.1l/lib/libcrypto.so.1.0.0 /usr/lib/libcrypto.so.1.0.0 ...

    • 现在配置并清理构建 蟒蛇
        7
  •  0
  •   AKS    9 年前

    在这里提到的修补程序之后,我可以使用非默认SSL运行python2.7.11 https://gist.github.com/eddy-geek/9604982

    然而,这样做并不是构建许多其他模块所需的_socket模块。例如,easy_install/pip开始失败,错误为Importer:没有名为_socket的模块

    在Module/Setup.dist中,我是否应该取消注释或注释该行 _套接字模块.o ?

    我看到生成了socketmodule.o和timemodule.o。但不是_socket.so 我错过了什么吗?