Coredump when compiling python with a custom opens

2019-01-25 10:57发布

When compiling python-3.4.0rc3 with a local openssl-1.0.1f shared install, make prints no error but then I get the following core dump on make install or 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 ?? ()

Here is the complete list of commands used

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

Notes:

  • OS is SUSE Linux Enterprise Server 11 (x86_64)
  • pointing python to a custom location for the lzma lib located in
  • openssl was built with ./config shared --openssldir=/data2/soft/openssl
  • openssl make test prints ALL TESTS SUCCESSFUL.
  • without the custom openssl *FLAGS, make install is successful and I get these results for make test: 71 tests OK. tests failed: test_cmd_line test_gdb test_smtpnet test_ssl

How can I fix this, or at least investigate what is going on ?

Edit 1--5:

The shared libs were generated correctly:

> 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

So I changed this in Setup :

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

And I changed back LDFLAGS/CFLAGS accordingly. But there still is a -lssl when I run make clean && make, because of the _hashopen module:

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

I guess it is the one causing the cores, because they are still there... I tried adding similar stuff to Setup file, but there is no commented item for this one and creating it causes another more cryptic failure:

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

Edit 6:

  • I couldn't find anyway to modify how _hashlib.so is generated, as there is too much Makefile magic involved (it doesn't appear anywhere, nor does '-lssl' yet both magically end up on the same line together
  • But I can get it linking dynamically to my own openssl through good old -I/-L:

    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)

  • Now the only problem is, gdb info shared still tells me another one is used at core-time ... but how ?

    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' -> shows nothing !
    • grep -RF 'python-2.6-64' /etc/ld.so.* -> idem
    • gcc -print-search-dirs | sed 's/:/\n/g' | grep python -> idem
    • find . -name '*.so*' | xargs ldd | grep ssl -> only gives me the good ones
    • Level 1 dependencies don't require any wrong ssl version either. This was checked with:
      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 -> shows nothing

So how does ld picks this wrong library if he cannot konow about it ?? It's not in any standard location (if it were in /lib I could understand...)

Solution:

Found how to statically link _hashlib thanks to this OpenOffice bug: though the -Wl,--exclude-libs=ALL" option didn't work either, it pointed me to the right lines in setup.py.

TL;DR Here is the patch to setup.py I applied.

And finally... it works !

@noloader I'm accepting your most complete answer as you help was invaluable, though the "exact" answer for anyone encountering this problem is to compile with the patch above.

7条回答
虎瘦雄心在
2楼-- · 2019-01-25 11:38

I couldn't find anyway to modify how _hashlib.so is generated, as there is too much Makefile magic involved (it doesn't appear anywhere, nor does '-lssl' yet both magically end up on the same line together

grep is your friend ;)

$ 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"]
查看更多
做个烂人
3楼-- · 2019-01-25 11:42

We had a similar problem. We are using apache httpd + mod_wsgi + python + django and our c++ module for the apache httpd which also uses openssl. Now everything is loaded within one httpd process, correct version of openssl shared lib was loaded (1.0.0l) with our c++ module. But as soon as we access the web, python loads the hashlib and exactly the same problem appears - segfault in openssl called from python.

Normally python compiles with whatever openssl is available at the default location and there is no way how to specify it without fiddling with setup.py or makefiles. Python developers should add configure setting --with_ssl=path.

We installed new openssl libs and rebuild python and other binaries but with no success. We mapped default libssl.so and libcrypto.so to the new openssl binaries with no success. Finally after reading this thread I realized that probably wrong headers are being used while compiling python. And that was the problem. Follow the step to workaround the problem:

  • there must not be incorrect version of openssl headers in /usr/include and default locations /usr/local/ssl, /usr/contrib/ssl (if you installed openssl-devel then uninstall it, or simply erase/rename the directory)

yum remove openssl-devel

  • make symbolic link to your openssl installation from /usr/local/ssl

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

  • ensure that the new openssl libs are accessible from /usr/lib (make symbolic links if it is not installed here)

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

  • now configure and clean build the python
查看更多
贪生不怕死
4楼-- · 2019-01-25 11:45

I am able to run python 2.7.11 with non-default SSL after patching fix mentioned here https://gist.github.com/eddy-geek/9604982

However, with this it's not building _socket module which is required by many other modules. for example, easy_install / pip started failing with error Importerr: no module named _socket

In Module/Setup.dist, am i suppose to uncomment or comment the line _socket socketmodule.o ?

I see socketmodule.o and timemodule.o getting generated. but not _socket.so Am i missing something ?

查看更多
男人必须洒脱
5楼-- · 2019-01-25 11:46

Another partial answer...

But I can get it linking dynamically to my own openssl through good old -I/-L:

...

Now the only problem is, gdb info shared still tells me another one is used at core-time ... but how ?

That's your good old friends -l and -L. Don't use them because they do this sort of thing all the time (take it from a guy who has suffered it in the past). Instead, specify the full path to libssl and libcrypto. E.g., use /data2/soft/openssl/lib/libssl.a.

查看更多
戒情不戒烟
6楼-- · 2019-01-25 11:49

How should I go about changing it ? Will adding a _ssl.c: gcc ... line anywhere override the default behaviour ? My Makefile skills are rusted and this beast is 1600+ lines long !!

Here are the files you want to look at:

$ 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

Here are the lines of interest in 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

Uncomment the lines and change Setup.dist to the following. I keep my OpenSSL in /usr/local/ssl, so that's how mine is setup below (you should use /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

Use the full path to the archive, and don't use -l. Be sure to add -ldl because OpenSSL needs it in this configuration.

Once you change Setup.dist, re-run ./configure to effect the changes.


After changing the above line to, here's what I look like after a 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 

You can test the static linking by using ldd or otool -L. You will not see an OpenSSL dependency. After make'ing, here's what I got:

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

No libssl or libcrypto dependencies to go wrong :) And make test ran fine (actually, one failed test due to a Python bug: 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
查看更多
手持菜刀,她持情操
7楼-- · 2019-01-25 11:57

This isn't an answer, just an observation after running though this with you:

$ 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 is really bad. Its used to make illegal programs work. Its better to fix the broken program and drop the -fwrapv. See Ian Lance Taylor's blog on Signed Overflow.

查看更多
登录 后发表回答