簡體   English   中英

使用自定義openssl版本編譯python時的Coredump

[英]Coredump when compiling python with a custom openssl version

在使用本地openssl-1.0.1f共享安裝編譯python-3.4.0rc3時, make打印沒有錯誤但是我在make install或make test上得到以下核心轉儲:

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指向位於的lzma lib的自定義位置
  • openssl是使用./config shared --openssldir=/data2/soft/openssl構建的
  • openssl make test打印所有TESTSFUCCESSFUL。
  • 沒有自定義openssl * FLAGS,make install是成功的,我得到這些結果進行make test: 71 tests OK. tests failed: test_cmd_line test_gdb test_smtpnet test_ssl 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時,仍然有一個-lssl,因為_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' 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 gcc -print-search-dirs | sed 's/:/\\n/g' | grep python - >同上
    • find . -name '*.so*' | xargs ldd | grep ssl 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 strace ./python ./Tools/scripts/run_tests.py 2>&1 | grep python-2.6-64 - >什么都沒顯示

那么,如果他不能知道ld怎么選擇這個錯誤的庫呢? 它不在任何標准位置(如果它在/ lib中我能理解......)

解:

通過這個OpenOffice錯誤找到了如何靜態鏈接_hashlib:雖然-Wl -Wl,--exclude-libs=ALL"選項也不起作用,但它指向了setup.py中的右側行。

TL; DR這是我應用的setup.py補丁

最后......它有效!

@noloader我接受你最完整的答案,因為你的幫助是無價的,盡管遇到這個問題的人的“確切”答案是用上面的補丁編譯。

 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下層版本,不支持TLS 1.2 )。

您可能正在加載錯誤版本的OpenSSL庫。 如果您可以在調試器下獲得行為不端的程序,請發出info shared以查看您實際加載的libcryptolibssl

ldd也可能有所幫助。 在Pyhton可執行文件上運行它: ldd /data2/soft/python3/python 我只能說它“可能”有幫助,因為OpenSSL是二進制兼容的,所以你可能只看到依賴,例如libcrypto.so.1.0.0 (在Mac OS X上使用otool -L )。 下面我使用了一個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 /data2/soft/openssl/lib/libssl.a / /data2/soft/openssl/lib/libcrypto.a /data2/soft/openssl/lib/libssl.a/data2/soft/openssl/lib/libcrypto.a

請注意 :在Mac OS X上不支持rpath 。對於Mac OS X,需要采取更多極端措施,因為鏈接器也不支持-Bstatic 你將不得不使用完整的路徑技巧。


 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時,我最近遇到了這個問題。 但我的程序也使用libeventlibevent使用系統的OpenSSL版本。 我通過重建libevent並強制它靜態鏈接到我的OpenSSL版本來修復它。

我該如何改變呢? 是否會在任何地方添加_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中感興趣的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

取消注釋行並將Setup.dist更改為以下內容。 我將我的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在此配置中需要它。

更改Setup.dist ,重新運行./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 

您可以使用lddotool -L測試靜態鏈接。 不會看到一個OpenSSL的依賴。 經過make “ING,這里是我的了:

$ 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)

沒有libssllibcrypto依賴項出錯:)並且make test運行正常(實際上,由於Python錯誤導致測試失敗: 問題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

這不是一個答案,只是在與你一起跑完之后的觀察:

$ 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的博客。

我無論如何都無法修改如何生成_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"]

另一個部分答案......

但我可以通過良好的舊-I / -L動態鏈接到我自己的openssl:

...

現在唯一的問題是,gdb info shared還告訴我另一個在核心時間使用......但是怎么樣?

那是你的老朋友-l-L 不要使用它們,因為它們總是這樣做(從過去遭受過它的那個人那里拿走它)。 而是指定libssllibcrypto完整路徑。 例如,使用/data2/soft/openssl/lib/libssl.a

我們遇到了類似的問題。 我們使用apache httpd + mod_wsgi + python + django和我們的c ++模塊用於apache httpd ,它也使用openssl 現在一切都在一個httpd進程中加載​​,正確版本的openssl共享庫已經加載(1.0.0l)我們的c ++模塊。 但是一旦我們訪問網頁,python就會加載hashlib並且出現完全相同的問題 - 在openssl中調用來自python的segfault。

通常python會編譯默認位置可用的openssl ,並且無法在不使用setup.py或makefile的情況下指定它。 Python開發人員應該添加配置設置--with_ssl=path

我們安裝了新的openssl庫並重建了python和其他二進制文件但沒有成功。 我們將默認的libssl.so和libcrypto.so映射到新的openssl二進制文件但沒有成功。 最后,在閱讀了這個帖子后,我意識到在編譯python時可能會使用錯誤的標題。 這就是問題所在。 按照步驟解決問題:

  • /usr/include和默認位置/usr/local/ssl/usr/contrib/ssl (如果你安裝了openssl-devel然后卸載它,或者只是擦除/重命名目錄)一定不能有不正確版本的openssl頭文件

yum remove openssl-devel

  • /usr/local/ssl創建指向openssl安裝的符號鏈接

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

  • 確保可以從/usr/lib訪問新的openssl庫(如果未安裝符號鏈接,請創建符號鏈接)

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

  • 現在配置並清理構建python

在修補此處提到的修補程序后,我可以使用非默認SSL運行python 2.7.11 https://gist.github.com/eddy-geek/9604982

但是,有了這個,它不會構建許多其他模塊所需的_socket模塊。 例如,easy_install / pip啟動失敗,錯誤導入器:沒有名為_socket的模塊

在Module / Setup.dist中,我想取消注釋或注釋行_socket socketmodule.o?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM