Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Add config to force OpenSsl error queue cleanup before Encrypt/Decrypt - #29186

Merged
pjanotti merged 2 commits into
dotnet:masterfrom
pjanotti:config.force.openssl.err.cleanup
Apr 21, 2018
Merged

Add config to force OpenSsl error queue cleanup before Encrypt/Decrypt#29186
pjanotti merged 2 commits into
dotnet:masterfrom
pjanotti:config.force.openssl.err.cleanup

Conversation

@pjanotti

@pjanotti pjanotti commented Apr 18, 2018

Copy link
Copy Markdown
Contributor

[EDIT: updating the names to the ones that were actually merged]

This is an escape valve in case the optimization of removing the calls to ERR_clear_error() for each SSL_write/SSL_read causes troubles. There will be a performance impact but depending on the scenario it can be a desired trade-off.

The AppContext switch is "System.Net.Security.SslStream.ForceClearOpenSslErrorQueue"
The env var is "DOTNET_SYSTEM_NET_SECURITY_SSLSTREAM_FORCECLEAROPENSSLERRORQUEUE"

This is a escape valve in case the optimization of removing the calls to ERR_clear_error() for each SSL_write/SSL_read causes troubles. There will be a performance impact but depending on the scenario it can be a desired trade-off.
@pjanotti pjanotti added this to the 2.1.0 milestone Apr 18, 2018
@pjanotti pjanotti self-assigned this Apr 18, 2018
@karelz karelz modified the milestones: 2.1.0, 2.2.0 Apr 18, 2018
@karelz

karelz commented Apr 18, 2018

Copy link
Copy Markdown
Member

@pjanotti fixing the milestone - it will go into master = 2.2. If we want it to 2.1, we need to cherry pick it + it would be good to have a tracking bug. Can you please create one?

@pjanotti

Copy link
Copy Markdown
Contributor Author

Done, #29188 created.

@pjanotti

Copy link
Copy Markdown
Contributor Author

@dotnet/dnceng OSX x64 seems stuck https://ci3.dot.net/job/dotnet_corefx/job/master/job/osx-TGroup_netcoreapp+CGroup_Debug+AGroup_x64+TestOuter_false_prtest/11570/consoleText after successful build.

@dotnet-bot test OSX x64 Debug Build

@mmitche

mmitche commented Apr 18, 2018

Copy link
Copy Markdown
Member

@pjanotti Not stuck, just backed up.

@pjanotti

Copy link
Copy Markdown
Contributor Author

Ops, then I didn't help by asking for another build...

if (!AppContext.TryGetSwitch("System.Net.Security.SslStream.ForceOpenSslErrorQueueCleanupBeforeEncryptDecrypt", out bool forceErrorQueueCleanup))
{
// AppContext wasn't used, try the environment variable.
string envVar = Environment.GetEnvironmentVariable("DOTNET_FORCE_OPENSSL_ERROR_QUEUE_CLEANUP_BEFORE_ENCRYPT_DECRYPT");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general I think we should keep the appctx switch name and the env var name to be as similar as possible, e.g.
System.Net.Security.SslStream.ForceClearOpenSslErrorQueue
and
DOTNET_SYSTEM_NET_SECURITY_SSLSTREAM_FORCECLEAROPENSSLERRORQUEUE


extern "C" int32_t CryptoNative_SslWrite(SSL* ssl, const void* buf, int32_t num)
{
if (g_forceOpenSslErrorQueueCleanupBeforeWriteRead)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this check/branch have any impact on the case where it's not set? i.e. the default case where the user doesn't set the flag? Presumably it's a drop in the bucket compared to the comparison, but it'd be good to know for sure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The performance with the config (default, optimization on) is indistinguishable compared to master - same test indicates that when the optimization is off there is a 5 to 15% extra time to complete the test (test based on your ConcurrentHttpsGet test, but I had to run it under Xunit since I couldn't get Benchmark.NET working against my local build).

private unsafe static readonly Ssl.SslCtxSetAlpnCallback s_alpnServerCallback = AlpnServerSelectCallback;
private static readonly IdnMapping s_idnMapping = new IdnMapping();

static OpenSsl()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Before this change, the compiler could make the Interop.OpenSsl class beforefieldinit. Adding this explicit static cctor is going to stop that from happening, which can have perf implications.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, perhaps initialize a field with a side effect? Let me know if you have any suggestions

@stephentoub

Copy link
Copy Markdown
Member

How far are we from having audited all of our calls? This may be naive, but it seems like the right answer is to audit all of the calls, make sure we're doing the right thing, and then we don't need a flag like this. If someone else in the process is using OpenSSL incorrectly, that's then their problem.

cc: @bartonjs

@maririos

Copy link
Copy Markdown
Contributor

@pjanotti Not stuck, just backed up.

Issue that is tracking the work to enable more OSX is https://github.com/dotnet/core-eng/issues/3284

@pjanotti

Copy link
Copy Markdown
Contributor Author

How far are we from having audited all of our calls?

I'm starting this work, first I wanted to address the ones that the debugger showed that were explicit putting errors in the queue in order to reduce noise. I should have a ball-park estimate for the amount of work by tomorrow.

We have to audit our calls but this is playing defense and having an option if something passes our combing.

@bartonjs bartonjs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Aside from the style comments, I question the purpose.

If the purpose is: "Leaked error states cause exceptions to be thrown during successful cases, and this helps applications move onto 2.1", then OK.

If the purpose is "the wrong exception is thrown, but it was throwing anyways, this makes it be the right exception" then I don't know it's useful enough to warrant a) change, and b) maintenance of that change.

extern "C" int32_t CryptoNative_SslRead(SSL* ssl, void* buf, int32_t num)
{
if (g_forceOpenSslErrorQueueCleanupBeforeWriteRead)
ERR_clear_error();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add the explicit braces. The only things in this file (and probably most of this library) which use an unbraced if are stacked if->returns

out int hashKeySize);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ForceOpenSslErrorQueueCleanupBeforeWriteRead")]
internal static extern void ForceOpenSslErrorQueueCleanupBeforeWriteRead();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OpenSsl in the name is a bit redundant

// Controls if ERR_clear_error is going to be called before SSL_write/SSL_read
static bool g_forceOpenSslErrorQueueCleanupBeforeWriteRead = false;

extern "C" void CryptoNative_ForceOpenSslErrorQueueCleanupBeforeWriteRead()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All of our extern functions should also be defined in the corresponding header.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No problem, I will follow it for consistency, but I'm a bit curious about the purpose of it. Do you know why?

@pjanotti

Copy link
Copy Markdown
Contributor Author

Leaked error states cause exceptions to be thrown during successful cases, and this helps applications move onto 2.1

Yes, this is the issue being addressed here.

We don't need this if we can be almost sure that we ourselves don't leave any errors on the queue. My initial count shows that we will have to review about 250 native calls, hopefully most of them should be trivial, but anyway this needs to be done carefully (both to not to regress perf nor lose error information).

@pjanotti

Copy link
Copy Markdown
Contributor Author

Failures on Ubuntu 14.04 per inspection of a random set seems related to sockets:

System.Net.Sockets.SocketException : Cannot assign requested address

@dotnet-bot test Outerloop Linux x64 Release Build
@dotnet-bot test Outerloop Linux x64 Debug Build
@dotnet-bot test Linux x64 Release Build
@dotnet-bot test Linux x64 Debug Build

@pjanotti
pjanotti merged commit 2750fdd into dotnet:master Apr 21, 2018
@pjanotti
pjanotti deleted the config.force.openssl.err.cleanup branch April 21, 2018 02:43
pjanotti pushed a commit to pjanotti/corefx that referenced this pull request May 1, 2018
dotnet#29186)

* Add config to force OpenSsl error queue cleanup before Encrypt/Decrypt

This is a escape valve in case the optimization of removing the calls to ERR_clear_error() for each SSL_write/SSL_read causes troubles. There will be a performance impact but depending on the scenario it can be a desired trade-off.

Fixes #29188
pjanotti pushed a commit to pjanotti/corefx that referenced this pull request May 4, 2018
pjanotti pushed a commit that referenced this pull request May 7, 2018
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
dotnet/corefx#29186)

* Add config to force OpenSsl error queue cleanup before Encrypt/Decrypt

This is a escape valve in case the optimization of removing the calls to ERR_clear_error() for each SSL_write/SSL_read causes troubles. There will be a performance impact but depending on the scenario it can be a desired trade-off.

Fixes dotnet/corefx#29188 


Commit migrated from dotnet/corefx@2750fdd
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants