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

Improved support for using s2n-tls from within an unloadable shared lib #3011

Merged
merged 5 commits into from
Aug 23, 2021

Conversation

justinboswell
Copy link
Contributor

@justinboswell justinboswell commented Aug 14, 2021

Resolved issues:

Resolves crash on exit in Java and PHP when using s2n-tls via the AWS CRT.

Description of changes:

Currently, s2n uses an atexit() handler to clean itself up. This is a guaranteed crash when s2n-tls is embedded in a shared library that can be unloaded.

A call to s2n_disable_atexit() prevents s2n from installing the atexit() handler, and adjusts s2n_cleanup() so that it will perform final cleanup when called from the main thread (defined as the thread s2n_init() was called from).

Additionally, after cleaning up its ENGINE/rand implementation, s2n now sets the libcrypto RAND engine and method to NULL, preventing a crash on shutdown as libcrypto tries to free the already freed (and in the case of a shared library, unloaded) ENGINE implementation.

Call-outs:

It may be advantageous to create a single API call to prepare s2n for use in an embedded/modular/plugin environment. That is something we could address in a follow-up, once this is working in target environments. The original draft of the prior change proposed an s2n_share_libcrypto() API, something singular feels like a good move for users.

Testing:

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor

@lrstewart lrstewart left a comment

Choose a reason for hiding this comment

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

You callout mentions eventually having a single API to set up S2N for certain environments. Is it still worth creating a separate API for just this aspect? Once we publish the API, we've committed ourselves to supporting it.

if (pthread_self() == main_thread && !atexit_cleanup) {
POSIX_ENSURE(s2n_cleanup_atexit_impl(), S2N_ERR_ATEXIT);
}
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return 0;
return S2N_SUCCESS;

@justinboswell
Copy link
Contributor Author

You callout mentions eventually having a single API to set up S2N for certain environments. Is it still worth creating a separate API for just this aspect? Once we publish the API, we've committed ourselves to supporting it.

I think it is, because you'd most likely only use these 2 calls together, and I think making developers have to divine the magic pairing is a worse experience than a single API call that just makes it work, and which we can tie any future lifetime behavior into.

@@ -83,7 +83,14 @@ struct s2n_connection;
* with S2N.
*/
S2N_API
extern void s2n_crypto_disable_init(void);
extern int s2n_crypto_disable_init(void);
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically this is a breaking change but hopefully no one has consumed it yet 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I'm counting on that. The good news is, even if they consumed it, this cannot cause a compile failure.

Copy link
Contributor

Choose a reason for hiding this comment

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

It still could, but unlikely: https://godbolt.org/z/zPeh99793

@lrstewart
Copy link
Contributor

lrstewart commented Aug 20, 2021

You callout mentions eventually having a single API to set up S2N for certain environments. Is it still worth creating a separate API for just this aspect? Once we publish the API, we've committed ourselves to supporting it.

I think it is, because you'd most likely only use these 2 calls together, and I think making developers have to divine the magic pairing is a worse experience than a single API call that just makes it work, and which we can tie any future lifetime behavior into.

I actually meant kind of the opposite :) Should we create this API (a separate API that we will have to continue supporting) if it provides a bad experience and the combined API is the end goal, or should we just create that combined API.

Comment on lines +45 to +46
int s2n_disable_atexit(void) {
const bool already_initialized = (main_thread != 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you make this comparison? The man page suggests it might not work: https://man7.org/linux/man-pages/man3/pthread_self.3.html You might need pthread_equal. And even then, can we guarantee 0 isn't a valid pthread_t?

Maybe use a separate variable for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch on the comparison! I had no idea

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm going to do a followup PR on this.

Comment on lines +94 to +95
* perform final cleanup now */
if (pthread_self() == main_thread && !atexit_cleanup) {
Copy link
Contributor

Choose a reason for hiding this comment

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

#3011 (comment) could be an issue for this comparison too

@justinboswell justinboswell merged commit f9fd819 into main Aug 23, 2021
@justinboswell justinboswell deleted the share-libcrypto branch August 23, 2021 22:23
@camshaft camshaft mentioned this pull request Aug 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants