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

Avoid frequent calls to CertificateValidationPal.IsLocalCertificateUsed #100513

Conversation

rzikm
Copy link
Member

@rzikm rzikm commented Apr 2, 2024

Closes #95687.

The affected code path is on Windows in mutually authenticated connections (i.e. with client certificate), and where client accesses either of:

  • IsMutuallyAuthenticated
  • LocalCertificate

Server side is unaffected, as well as client side without client certificate.


BenchmarkDotNet v0.13.11-nightly.20231126.107, Windows 11 (10.0.22631.3296/23H2/2023Update/SunValley3)
Intel Core i9-10900K CPU 3.70GHz, 1 CPU, 20 logical and 10 physical cores
.NET SDK 8.0.300-preview.24201.7
  [Host]     : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
  Job-JOWNWG : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2
  Job-UGFCLX : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2

PowerPlanMode=00000000-0000-0000-0000-000000000000  IterationTime=250.0000 ms  MaxIterationCount=20  
MinIterationCount=15  WarmupCount=1  

Method Job Toolchain Mean Error StdDev Median Min Max Ratio Allocated Alloc Ratio
IsMutuallyAuthenticated Job-JOWNWG \95687-SslStreamIsMutuallyAuthenticated-calls-are-expensive-on-Windows\corerun.exe 5.271 ns 0.0428 ns 0.0334 ns 5.273 ns 5.202 ns 5.320 ns 0.000 - 0.00
IsMutuallyAuthenticated Job-UGFCLX \main\corerun.exe 62,898.672 ns 1,125.7018 ns 997.9053 ns 63,306.704 ns 61,270.539 ns 64,574.663 ns 1.000 32 B 1.00

@@ -360,6 +360,9 @@ private async Task ForceAuthenticationAsync<TIOAdapter>(bool receiveFirst, byte[
}

token.ReleasePayload();

// reset the cached flag which has potentially outdated value.
_localClientCertificateUsed = null;
Copy link
Member

Choose a reason for hiding this comment

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

Are there threading issues here? bool? is two bool fields (one for null or not, one for the value) and they're not necessarily updated or read atomically. If someone was reading IsLocalClientCertificateUsed while this was being reset, might they end up reading an incorrect value, e.g. if this flipped the value from true to false before flipping the null state?

Copy link
Member Author

@rzikm rzikm Apr 4, 2024

Choose a reason for hiding this comment

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

The value can go only from false to true, and that happens only during renegotiation/post-handshake authentication, which is usually at most once per connection.

The only thing I can think of is

  • thread 1 writes HasValue = false (part of the null assignment)
  • thread 2 accesses IsLocalClientCertificateUsed, assigning HasValue = true, Value = true
  • thread 1 writes Value = false (if that is how null assignment work)

Actual calculation of the new value is expensive (which is why I wanted to cache it) so this ordering is not likely, but still possible in theory.

If you still see any concerns than I think we can either move to something like Lazy (at the cost of small allocation) or fetching the new value here (potential small perf hit on (windows) client in mutual auth scenario).

Copy link
Member

Choose a reason for hiding this comment

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

I'd just change the storage to something written atomically, e.g. use an int that's 0 for uninitialized, 1 for true, -1 for false.

@rzikm rzikm requested a review from stephentoub April 4, 2024 18:18
@rzikm rzikm merged commit bc2bd2b into dotnet:main Apr 8, 2024
87 checks passed
matouskozak pushed a commit to matouskozak/runtime that referenced this pull request Apr 30, 2024
…ed (dotnet#100513)

* Avoid frequent calls to CertificateValidationPal.IsLocalCertificateUsed

* Code review feedback
@github-actions github-actions bot locked and limited conversation to collaborators May 8, 2024
@karelz karelz added this to the 9.0.0 milestone May 14, 2024
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.

SslStream.IsMutuallyAuthenticated calls are expensive on Windows
4 participants