runtime: Crash on WindowsCryptographicException on net60 GA
Description
System.AggregateException: One or more errors occurred. (Unknown error (0xc1000008)) —> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Unknown error (0xc1000008) at Internal.Cryptography.HashProviderCng.AppendHashData(ReadOnlySpan`1 source) at Internal.Cryptography.HashProvider.AppendHashData(Byte[] data, Int32 offset, Int32 count) at System.Security.Cryptography.SHA256.Implementation.HashCore(Byte[] array, Int32 ibStart, Int32 cbSize) at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer) at Host.CLI.Program.<>c__DisplayClass9_2.<<BuildAsync>b__3>d.MoveNext() in C:\work\curiosity\curiosity-ai-website\tools\host\Program.cs:line 280 — End of stack trace from previous location — at Host.CLI.Program.BuildAsync(String path, String buildPath, String templatePath, String translationPath) in C:\work\curiosity\curiosity-ai-website\tools\host\Program.cs:line 296 — End of inner exception stack trace — at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait() at Host.CLI.Delayed.<CreateScheduledQueueChecker>g__CheckBacklog|5_1() in C:\work\curiosity\curiosity-ai-website\tools\host\Delayed.cs:line 71 at Host.CLI.Delayed.<>c.<CreateScheduledQueueChecker>b__5_0(Object _) in C:\work\curiosity\curiosity-ai-website\tools\host\Delayed.cs:line 49 at System.Threading.TimerQueueTimer.<>c.<.cctor>b__27_0(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) — End of stack trace from previous location — at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.TimerQueueTimer.CallCallback(Boolean isThreadPool) at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool) at System.Threading.TimerQueue.FireNextTimers() at System.Threading.TimerQueue.AppDomainTimerCallback(Int32 id)
Reproduction Steps
The app in question is a simple web host, accessing the page via the edge browser.
Expected behavior
No crash
Actual behavior
Process crashes hard with an uncaught exception
Regression?
Yes. The issue never happen till I installed the net60 GA SDK installed this morning.
Known Workarounds
No response
Configuration
Window x64
dotnet --list-sdks
2.1.526 [C:\Program Files\dotnet\sdk]
2.1.617 [C:\Program Files\dotnet\sdk]
2.1.701 [C:\Program Files\dotnet\sdk]
2.1.818 [C:\Program Files\dotnet\sdk]
2.2.101 [C:\Program Files\dotnet\sdk]
2.2.301 [C:\Program Files\dotnet\sdk]
3.0.100-preview8-013656 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.200 [C:\Program Files\dotnet\sdk]
3.1.301 [C:\Program Files\dotnet\sdk]
3.1.415 [C:\Program Files\dotnet\sdk]
5.0.104 [C:\Program Files\dotnet\sdk]
5.0.209 [C:\Program Files\dotnet\sdk]
5.0.303 [C:\Program Files\dotnet\sdk]
5.0.403 [C:\Program Files\dotnet\sdk]
6.0.100-rc.1.21458.32 [C:\Program Files\dotnet\sdk]
6.0.100 [C:\Program Files\dotnet\sdk] <---- App is running on this now
Other information
No response
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 20 (11 by maintainers)
Hi @vcsjones, I’ve not observed the issue anymore! Nice to hear it uncovered another issue nevertheless! Thanks!
It looks like you are using an instance of
SHA256
concurrently. You have a property, field, or local instance namedSha256
that is concurrently (Task.WhenAll
) computing the file hashes.If you are targeting
net5.0
or higher, you can change it to this:HashData
was introduced in .NET 5. It is a static method and it is thread safe.To round things out here:
@vcsjones I have a repro case for a similar, if not identical, issue:
This breaks:
If you want things to break in .NET6 just leave the 4th line commented. If you want it to not break, uncomment line 4.
If you re-initialize a hasher after calling TransformBlock and before calling TransformFinalBlock, you corrupt the hasher and it fails.
EDIT: Thanks to @EvgeniyZ-ru for bringing this issue to my attention, and working with me to provide the information I needed to distill a testcase 😃
A few guesses, since I don’t have a lot to go on.
I suspect it is might be because the
HMACSHA512
encryptor
field is being accessed from multiple threads. Instances ofHMACSHA512
are not thread safe.I can reproduce this exception by using an
HMACSHA512
instance between threads:That will quickly give me the same issue as described in the original post.
At this point I can only suggest that you confirm with the library author that no instance of a hash or HMAC algorithm is being used by two or more threads, concurrently.
If that is indeed the case, I would recommend creating a new instance of the hash / HMAC algorithm per-thread, or just always as-needed. Alternatively, using the
HMACXYZ.HashData
one-shot static methods that were introduced in .NET 5 for digests, and .NET 6 for HMACs.