BUG: RTLD_GLOBAL dlopen flag causes segfaults w/ pynacl & libsodium #1878
Description
What pyzmq version?
25.1.0
What libzmq version?
4.3.4
Python version (and how it was installed)
Python 3.10.9
OS
Linux
What happened?
When pyzmq is built without bundling libsodium, tweetnacl is bundled. Pyzmq performs a dlopen of libzmq with the RTLD_GLOBAL
which causes tweetnacl's functions to resolved rather than libsodium's functions. This will cause segfaults if using PyNaCl with pyzmq.
Code to reproduce bug
virtualenv venv
source venv
# When no libsodium is present, libzmq bundles tweetnacl
pip install --no-binary=':all:' pyzmq
nacl_test.py
import zmq
from nacl.public import PublicKey, PrivateKey, SealedBox
# Generate Bob's private key, as we've done in the Box example
skbob = PrivateKey.generate()
pkbob = skbob.public_key
# Alice wishes to send a encrypted message to Bob,
# but prefers the message to be untraceable
sealed_box = SealedBox(pkbob)
# This is Alice's message
message = b"Kill all kittens"
# Encrypt the message, it will carry the ephemeral key public part
# to let Bob decrypt it
encrypted = sealed_box.encrypt(message)
unseal_box = SealedBox(skbob)
# decrypt the received message
plaintext = unseal_box.decrypt(encrypted)
print('done')
Running nacl_test.py will result in a segfault:
$ python nacl_test.py
Segmentation fault
The segfault is called because libsodium's crypto_secretbox_detached
calls crypto_core_hsalsa20
bit it's tweetnacl's version of crypto_core_hsalsa20
instead of libsodium's version.
### Traceback, if applicable
```shell
38 bt
39 #0 0x00007f568e191b8f in raise () from /lib64/libpthread.so.0
40 #1 <signal handler called>
41 #2 0x00007f5685953ab5 in core (out=out@entry=0x7ffc12448270 "\204\202\324ф\326\a\225\247\362\235\203\331\060\251V \204D\022\374\177", in=in@entry=0x7ffc124484c0 "\273\003\241 \302ֽ\025\312NK\265\274\030\020\371\231Ou\313]:\330\"\250GvO",
42 k=k@entry=0x7ffc12448420 "\227\247V\363\246\355\364I2\277\346!\030ב\213\n9\306w\232\002\301\366 t\314u/C\351s)\267", c=c@entry=0x0, h=h@entry=1) at bundled/zeromq/src/tweetnacl.c:116
43 #3 0x00007f568595638f in crypto_core_hsalsa20 (out=out@entry=0x7ffc12448270 "\204\202\324ф\326\a\225\247\362\235\203\331\060\251V \204D\022\374\177",
44 in=in@entry=0x7ffc124484c0 "\273\003\241\302ֽ\025\312NK\265\274\030\020\371\231Ou\313]:\330\"\250GvO", k=k@entry=0x7ffc12448420 "\227\247V\363\246\355\364I2\277\346!\030ב2 13\n9\306w\232\002\301\366 t\314u/C\351s)\267", c=c@entry=0x0)
45 at bundled/zeromq/src/tweetnacl.c:163
46 #4 0x00007f56823a445c in crypto_secretbox_detached (c=c@entry=0x32c2240 "", mac=mac@entry=0x32c2230 "", m=m@entry=0x7f56878eadd0 "Kill all kittens", mlen=mlen@entry=16,
47 n=n@entry=0x7ffc124484c0 "\273\003\241\302ֽ\025\312NK\265\274\030\020\371\231Ou\313]:\330\"\250GvO", k=k@entry=0x7ffc12448420 "\227\247V\363\246\355\364I2\277\346!\030ב\213 \n9\306w\232\002\301\366 t\314u/C\351s)\267")
More info
To work around the issue you can make sure to import nacl before pyzmq.. That'll allow nacl to work properly, however I'm un-suer if it would have any adverse effects on pyzmq with curve support. I suspect it may.
Another work around is to make sure libsodium's dlopen call uses the RTLD_DEEPBIND
flag. This could also have adverse effects.