dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.5k stars 10.04k forks source link

ObjectDisposedException on HTTP/2 connection abort #51310

Closed amcasey closed 1 year ago

amcasey commented 1 year ago

Is there an existing issue for this?

Describe the bug

There's a race between shutting down the connection and ceasing to flush output that sometimes results in an ObjectDisposedException (of SslStream) when the connection is aborted.

Exception stack

at System.Net.Security.SslStream.<ThrowIfExceptional>g__ThrowExceptional|138_0(ExceptionDispatchInfo e) in /_/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs:line 849
at System.Net.Security.SslStream.WriteAsync(ReadOnlyMemory`1 buffer, CancellationToken cancellationToken) in /_/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.cs:line 817
at System.IO.Pipelines.StreamPipeWriter.<FlushAsyncInternal>d__39.MoveNext()
at System.Threading.Tasks.ValueTask`1.get_Result() in /_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs:line 786
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs:line 126
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeWriterHelpers.ConcurrentPipeWriter.<FlushAsyncAwaited>d__23.MoveNext() in src\Servers\Kestrel\Core\src\Internal\Infrastructure\PipeWriterHelpers\ConcurrentPipeWriter.cs:line 154
at System.Threading.Tasks.ValueTask`1.get_Result() in /_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs:line 786
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs:line 126
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeWriterHelpers.TimingPipeFlusher.<TimeFlushAsyncAwaited>d__9.MoveNext() in src\Servers\Kestrel\Core\src\Internal\Infrastructure\PipeWriterHelpers\TimingPipeFlusher.cs:line 89

The flush appears to be from

[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2FrameWriter.WriteDataAsync(int streamId, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl.StreamOutputFlowControl flowControl, System.Buffers.ReadOnlySequence<byte> data, long dataLength, bool endStream, bool firstWrite) Line 496
[Async] Microsoft.AspNetCore.Server.Kestrel.Core.dll!Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2OutputProducer.ProcessDataWrites() Line 467

The stream appears to be disposed at

at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.MySslStream.DisposeAsync() in src\Servers\Kestrel\Core\src\Middleware\HttpsConnectionMiddleware.cs:line 620
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context) in src\Servers\Kestrel\Core\src\Middleware\HttpsConnectionMiddleware.cs:line 218

Expected Behavior

No response

Steps To Reproduce

I've only seen this during a simulated Rapid Reset attack.

Exceptions (if any)

ObjectDisposedException

.NET Version

No response

Anything else?

No response

amcasey commented 1 year ago

The impact is basically just an extra log message and synchronizing the two appears difficult, so I don't believe this is worth fixing.