-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Clean the OpenSSL error queue more consistently #65148
Conversation
* The exception is based on the oldest error in the queue, instead of the newest * Operations whose failure can result in an exception should be clearing the queue at the start of that operation, and at any time an error has been inspected and suppressed. For this change, each shim function was evaluated based on its semantics. The callsites weren't checked to verify that failure from a non-error-queue routine aren't throwing a queue-based exception.
Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones Issue DetailsThis change started with the intent of changing the error code / message from an OpenSSL-based Having fully developed the experiment, data showed that while for EVP_PKEY2PKCS8 the first (of
|
@@ -102,6 +104,8 @@ otherwise. | |||
*/ | |||
const ASN1_TIME* CryptoNative_GetX509NotBefore(X509* x509) | |||
{ | |||
// No error queue impact. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I almost preemptively removed all of these comments, since they aren't as relevant with "keep using the last error in the queue". Clearly, I didn't.
- Why remove: They were added to justify a lack of ERR_clear_error, when ERR_clear_error was necessary producing correct exceptions.
- Why keep: They represent the output of white-box investigation of the code behind the code.
- Why remove: They could be invalidated.
- Why keep: Uh... it made opening the PR easier.
I have to do something to deal with merge conflicts no matter what... so thought I'd open the floor for a keep or cut discussion.
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some questions. Also, in the original issue:
Each operation probably wants to start off with ERR_clear_error(). It's relatively cheap these days.
(Probably worth a perf measurement to quantify this).
Do we have any sense of the perf impact of this, or confident enough that it's a cheap operation?
src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
Outdated
Show resolved
Hide resolved
In the shim version (CryptoNative_ErrClearError) I wrapped the call with __rdtsc. It's not "free" but it's "pretty cheap". But "pretty cheap" still felt slightly expensive when put in front of a field read.
|
Also, for a sense of scale on the __rdtsc values, some RSAOpenSsl.SignHash calls:
|
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
Outdated
Show resolved
Hide resolved
Since no one asked for the comments to be deleted, I left them all in. But updated the two that had been called out. (I also looked again at DSA_size and ECDSA_size, and agree they are "no impact"... and will get rewritten to be EVP_PKEY_size anyways) |
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs
Outdated
Show resolved
Hide resolved
…aphy.Native/Interop.ERR.cs Co-authored-by: Kevin Jones <vcsjones@github.com>
Fixes dotnet#44689 As of dotnet#65148, libraries use different approach to handling OpenSSL errors. The original assert which would be hit if a previous operation left errors in the queue is no longer necessary as all OpenSSL calls are prepended by `ERR_clear_error()` to make sure the latest (and most relevant) error is reported.
Fixes #44689 As of #65148, libraries use different approach to handling OpenSSL errors. The original assert which would be hit if a previous operation left errors in the queue is no longer necessary as all OpenSSL calls are prepended by `ERR_clear_error()` to make sure the latest (and most relevant) error is reported.
@bartonjs @vcsjones this showed-up in the 6.0 vs 7.0-rc2 perf report. Seems like this change regressed one benchmark on non-Windows configs. Should this be expected (by design)? Graph of the historical data: 3a4ade3...45a9548 is the range of commits in which the benchmark results changed, in case you think something else caused it. Here's the report data: System.Security.Cryptography.Tests.Perf_Rfc2898DeriveBytes.DeriveBytes
|
Ahh, thank you. We had a bug in our search process and missed that. |
This change started with the intent of changing the error code / message from an OpenSSL-based
exception from the most recent error in the queue to the oldest error that was produced after the
operation started. This was motivated mostly by
EVP_PKEY2PKCS8(pkey)
incorrectly indicating amalloc failure after producing the original/correct error that
pkey
did not have a private keyportion.
Having fully developed the experiment, data showed that while for EVP_PKEY2PKCS8 the first (of
two) errors was the better one, for everything else with more than one error reported, the last
error was at least as good as, and often better, than the first error. With that data in hand, this
change now represents more consistently cleaning the error queue, and reducing the overhead
in producing the exception objects.
Closes #55973.