Skip to content

BUG: RTLD_GLOBAL dlopen flag causes segfaults w/ pynacl & libsodium #1878

Open
@dwoz

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.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions