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

Fix context locking #9590

Closed
wants to merge 5 commits into from
Closed

Conversation

mattcaswell
Copy link
Member

Some parts of OPENSSL_CTX intialisation can get quite complex (e.g. RAND).
This can lead to complex interactions where different parts of the library
try to initialise while other parts are still initialising. This can lead
to deadlocks because both parts want to obtain the init lock.

We separate out the init lock so that it is only used to manage the
dynamic list of indexes. Each part of the library gets its own
initialisation lock.

Fixes #9454

I also simplified properties initialisation because there were some thread santizer issues cropping up in this area too. Finally I fixed some data races in EVP_CIPHER_fetch and EVP_MD_fetch.

There are still some thread sanitizer issues coming from evp_test that I haven't looked at yet, but I believe they are unrelated issues to those addressed here.

Some parts of OPENSSL_CTX intialisation can get quite complex (e.g. RAND).
This can lead to complex interactions where different parts of the library
try to initialise while other parts are still initialising. This can lead
to deadlocks because both parts want to obtain the init lock.

We separate out the init lock so that it is only used to manage the
dynamic list of indexes. Each part of the library gets its own
initialisation lock.

Fixes openssl#9454
Simplify the initialisation of the core by pre-initialising properties.
Don't modify the cipher/md we just fetched - it could be shared by multiple
threads.
@mattcaswell
Copy link
Member Author

This is an alternative to #9513.


if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data)) {
crypto_cleanup_all_ex_data_int(ctx);
goto err;
}

/* Everything depends on properties, so we also pre-initialise that */
if (!ossl_property_parse_init(ctx))
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 that do_method_store_init might be a better initialisation call under a openssl_ctx_run_once cover.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed the openssl_ctx_run_once because it was one of the causes of the lock order inversion issues. By moving it here (during initialisation of the OPENSSL_CTX) we know that it won't be shared by any other threads yet so can avoid the extra lock. I'm slightly confused by your reference to do_method_store_init - since such a function doesn't exist. Or are you suggesting I create it? If so, the only thing it would do would call ossl_property_parse_init() I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

do_method_store_init() is in crypto/property/property.c. It's the RUN_ONCE that calls ossl_property_parse_init() (and that's the only thing it does).

The ossl_property_parse_init() function can safely be called multiple times, it is preloading our property names and the Boolean values. If any already exist, they aren't added repeatedly.

So it would be safe to leave this as it is (and perhaps remove do_method_store_init() completely).

crypto/context.c Show resolved Hide resolved
crypto/evp/digest.c Show resolved Hide resolved
@paulidale paulidale added this to In progress in 3.0 New Core + FIPS via automation Aug 14, 2019
@paulidale paulidale added the branch: master Merge to master branch label Aug 14, 2019
@mattcaswell
Copy link
Member Author

Fixup commits pushed following review feedback.

Copy link
Contributor

@paulidale paulidale left a comment

Choose a reason for hiding this comment

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

Feel free to remove do_method_store_init() too, or it can be done in a separate PR.

Copy link

@mxmauro mxmauro left a comment

Choose a reason for hiding this comment

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

Tested the fix in a real app using OpenSSL.

After updating OpenSSL the issue appeared while trying to parse a PKCS12 certificate at the same time other thread is initializing a SSL context.

This patch solves the issue.

Regards,
Mauro.

3.0 New Core + FIPS automation moved this from In progress to Reviewer approved Aug 28, 2019
@mattcaswell
Copy link
Member Author

Pushed. Thanks.

3.0 New Core + FIPS automation moved this from Reviewer approved to Done Aug 29, 2019
levitte pushed a commit that referenced this pull request Aug 29, 2019
Some parts of OPENSSL_CTX intialisation can get quite complex (e.g. RAND).
This can lead to complex interactions where different parts of the library
try to initialise while other parts are still initialising. This can lead
to deadlocks because both parts want to obtain the init lock.

We separate out the init lock so that it is only used to manage the
dynamic list of indexes. Each part of the library gets its own
initialisation lock.

Fixes #9454

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from #9590)
levitte pushed a commit that referenced this pull request Aug 29, 2019
Simplify the initialisation of the core by pre-initialising properties.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from #9590)
levitte pushed a commit that referenced this pull request Aug 29, 2019
Don't modify the cipher/md we just fetched - it could be shared by multiple
threads.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from #9590)
@mxmauro
Copy link

mxmauro commented Aug 29, 2019

Hi guys, one question. I understand you add the patch to the 3.0 version but what about 1.1.x? So many commits and PR that I'm lost.

Thanks.

@mattcaswell
Copy link
Member Author

Hi guys, one question. I understand you add the patch to the 3.0 version but what about 1.1.x? So many commits and PR that I'm lost.

This PR fixes issues in the OPENSSL_CTX type. An OPENSSL_CTX can be considered like a library wide "scope". See also:

https://www.openssl.org/docs/manmaster/man3/OPENSSL_CTX.html

OPENSSL_CTX is a newly introduced concept in 3.0, so this issue does not affect 1.1.x and earlier.

@mattcaswell
Copy link
Member Author

You might also like to read the 3.0 design document which explains how all these things fit together.

@mxmauro
Copy link

mxmauro commented Aug 29, 2019

Thanks @mattcaswell. I just realized 1.1.1 is in its specific branch and master has the new 3.0 code.

Kind regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
branch: master Merge to master branch
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

ThreadSanitizer reports lock-order-inversion in evp_extra_test
4 participants