Writeable memory execution ('execmem') with python-cryptography 1.0

Create issue
Issue #231 wontfix
Adam Williamson created an issue

Hi, folks. I've been debugging a problem I found when upgrading a Fedora server box to Fedora 23. The long story is here:

https://bugzilla.redhat.com/show_bug.cgi?id=1277224

but here's the short story:

  1. Install Fedora 23
  2. setsebool -P deny_execmem on
  3. dnf install python-cryptography
  4. python -c 'from cryptography.hazmat.bindings.openssl.binding import Binding'

This will crash. It causes a problem in practice because on Fedora, SELinux denies such 'execmem' operations for processes run by httpd, and the above ultimately happens when something does import requests if python-ndg-httpsclient is installed, and FreeIPA - the thing I'm actually running on the affected box - does that in a WSGI server process. The setsebool command applies the same restriction to commands launched by a regular user, for ease of reproduction.

I talked to the python-cryptography devs about this, and they said:

<Alex_Gaynor> adamw: it looks like it's blowing up on any closure being created, so I think this is a cffi or libffi bug, not a cryptography one.

I'll attach the C backtrace from the crash.

Comments (8)

  1. Adam Williamson reporter

    Downgrading python-cryptography to 0.9 works around this problem. The major change between 0.9 and 1.0 was "Switched to the new cffi set_source out-of-line API mode for compilation", so use of that API mode may well be what causes this problem.

  2. Armin Rigo

    It seems that nowadays libffi provides an interface to replace ffi_prep_closure() and the hacks done in cffi's malloc_closure.h (which come from old code in ctypes): namely, ffi_closure_alloc() and ffi_closure_free() and ffi_prep_closure_loc(). We could try to kill malloc_closure.h and use this modern interface. Then, hopefully, it should either work or we can really blame it to libffi :-/

  3. Armin Rigo

    Here's an example of ffi_closure_alloc(), tweaked to remove compiler warnings and a bug on 64-bit big-endian machines(!) and to test allocating several closures together instead of just one. If people could try to compile and run this small C example on a variety of platforms, it would be cool! See attachment. Expected output:

    Before bound_put()
    Hello World!
    Result is 1
    
  4. Christian Heimes

    The sample code works on my Fedora test server and on my Raspberry Pi. I don't have access to big endian machines anymore. Trent's snakebite project has been dead for years.

    X86_64 with execmem prevention

    $ sudo setsebool -P deny_execmem on
    $ uname -s -r -m
    Linux 4.2.3-300.fc23.x86_64 x86_64
    $ gcc -v
    ...
    gcc version 5.1.1 20150618 (Red Hat 5.1.1-4) (GCC)
    $ rpm -q libffi
    libffi-3.1-8.fc23.x86_64
    $ gcc -lffi ffi_closure_alloc_test.c 
    $ ./a.out
    Before bound_put()
    Hello World!
    Result is 1
    

    raspberry pi

    $ uname -s -r -m
    Linux 3.18.11+ armv6l
    $ dpkg -s libffi5
    ...
    Architecture: armhf
    Source: libffi (3.0.10-3)
    $ gcc -v
    ...
    gcc version 4.6.3 (Debian 4.6.3-14+rpi1) 
    $ gcc -lffi ffi_closure_alloc_test.c 
    $ ./a.out 
    Before bound_put()
    Hello World!
    Result is 1
    
  5. Armin Rigo

    Marking this as a "won't fix". For people that really want to try, there is the unmerged ffi_closure_alloc branch. The issue is that ffi_closure_alloc() is buggy in case of fork() if we're running SELinux (both with the setting deny_execmem turned on or off). We could think it is a theoretical issue only---even so, getting a possibly exploitable crash because we're running SELinux should trigger alarms in security-minded people. But the truth is that the issue is not theoretical: it was already discussed a few times about ctypes, e.g. https://sourceware.org/ml/libffi-discuss/2009/msg00320.html .

    So I'm keeping the status quo and not calling the buggy ffi_closure_alloc(). I documented the deny_execmem issue here: http://cffi.readthedocs.org/en/latest/using.html#callbacks (may take a couple of days to show up, when I release cffi 1.3.1). For what it's worth I also made a CPython bug report with the ctypes issue: http://bugs.python.org/issue25653

  6. Log in to comment