Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Python OpenSSL locking callback and replace it with one in C #3201

Closed
wants to merge 1 commit into from

Conversation

aglasgall
Copy link

@aglasgall aglasgall commented Oct 18, 2016

The Python OpenSSL locking callback is unsafe; if GC is triggered
during the callback's invocation, it can result in the callback being
invoked reentrantly, which can lead to deadlocks. This patch replaces
it with one in C that gets built at compile time via cffi along with
the rest of the OpenSSL binding.

This is a straight lift of the callback and setup code from Python 3.5.2's _ssl module; the only changes were removing #ifs conditioned on various openssl versions because cryptography's minimum openssl version is higher than any of the conditioned blocks.

There are still several issues remaining after replacing it; in particular, the interpreter at least sometimes hangs on exit unless cryptography.hazmat.backends.openssl.backend.activate_builtin_random() is used (and though I've not seen it deadlock/hang if it is, that doesn't mean it won't), and I've also seen it dump core and abort because:

Fatal Python error: could not acquire lock for <_io.BufferedWriter name=''> at interpreter shutdown, possibly due to daemon threads

So we still have work to do, but this is a start.

This is for #3195.

The Python OpenSSL locking callback is unsafe; if GC is triggered
during the callback's invocation, it can result in the callback being
invoked reentrantly, which can lead to deadlocks. This patch replaces
it with one in C that gets built at compile time via cffi along with
the rest of the OpenSSL binding.
@mention-bot
Copy link

@aglasgall, thanks for your PR! By analyzing the history of the files in this pull request, we identified @public, @tiran and @alex to be potential reviewers.

@alex
Copy link
Member

alex commented Oct 18, 2016

Jenkins, ok to test.

@aglasgall
Copy link
Author

Build failures are I think because I imported sysconfig to get at WITH_THREAD to mimic _ssl.c's behavior of only installing the callback if threading is enabled. There's probably a better way of doing that.



if sysconfig.get_config_var("WITH_THREAD"):
FUNCTIONS += """
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need an additional guard for OpenSSL < 1.1.0 and not LibreSSL. OpenSSL 1.1.0 has its own locking code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 1.1.0 just noops the methods, but I agree we should guard.

if sysconfig.get_config_var("WITH_THREAD"):
# Use Python's implementation if available, importing _ssl
# triggers the setup for this.
__import__("ssl")
Copy link
Contributor

@tiran tiran Oct 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to import the ssl module. Just try to import the _ssl C extension module.

try:
    __import__('_ssl')
except ImportError:
    pass

Copy link
Contributor

@tiran tiran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment about the provenance of the code. For both legal and maintenance reasons you should indicate that the code has been copied from CPython's Modules/_ssl.c.

@reaperhulk
Copy link
Member

@tiran Is it possible to reconcile the Python license with our Apache/BSD dual license? I want to be sure we're in the clear on code import like this, but I am utterly unfamiliar with the actual provisions of the license CPython is provided under.

Copy link
Member

@reaperhulk reaperhulk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mostly looks good to me. A few very small comments. We definitely need to determine what the legal status of a code import like this is though.

"""

if sysconfig.get_config_var("WITH_THREAD"):
INCLUDES += """
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit, let's put this all on one line.

@@ -34,6 +42,7 @@
*/
extern "Python" int Cryptography_rand_bytes(unsigned char *, int);
extern "Python" int Cryptography_rand_status(void);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit, no newline here.

# If nothing else has setup a locking callback already, we set up
# our own
if not lib._setup_ssl_threads():
raise InternalError("Threading is enabled and cryptography is"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having this branch let's just do an _openssl_assert. Otherwise we'll have a coverage issue since we can't test this branch.



if sysconfig.get_config_var("WITH_THREAD"):
FUNCTIONS += """
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 1.1.0 just noops the methods, but I agree we should guard.

@tiran
Copy link
Contributor

tiran commented Oct 22, 2016

@reaperhulk I'm not a lawyer. You can ask VanL about the license.

@reaperhulk
Copy link
Member

To keep this PR updated: I have an open question to Van :)

@alex
Copy link
Member

alex commented Nov 8, 2016

Closing this in favor of #3226 which I'll use to drive this to completion. Thanks for diagnosing this and getting the ball rolling on a patch.

@alex alex closed this Nov 8, 2016
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 23, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants