From 8587d13a2764c025277d628471984bae8e16427c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= Date: Mon, 10 Jul 2023 06:40:17 +0000 Subject: [PATCH 1/2] Merged PR 32138: [7.0] Fixed stream capacity leaking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Description:** Prevent clients from overcoming defined stream limits by sending already closed streams. MSRC 79848  - Quic and Kestrel ASP.NET Kestrel stream flow control issue causing leak **Risk:** Low: the fix postpones releasing stream capacity after the stream is released from memory. **Validation:** Added test simulating the repro case. **Impacted assemblies:** System.Net.Quic.dll msquic.dll - native, part of Windows runtime --- eng/Versions.props | 2 +- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 2 +- .../Net/Quic/Interop/msquic_generated.cs | 1 + .../src/System/Net/Quic/QuicConnection.cs | 2 + .../tests/FunctionalTests/MsQuicTests.cs | 45 +++++++++++++++++-- .../System.Net.Quic.Functional.Tests.csproj | 1 + 6 files changed, 48 insertions(+), 5 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 8108e43a6771b2..f765d74d3336a4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -179,7 +179,7 @@ 7.0.0-rtm.23218.4 - 2.1.1 + 2.2.2 7.0.0-alpha.1.22459.1 11.1.0-alpha.1.23115.1 diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index 63b4a827d6790b..b6552b56e9efba 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -18,7 +18,7 @@ internal sealed unsafe partial class MsQuicApi { private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000); - private static readonly Version MinMsQuicVersion = new Version(2, 1); + private static readonly Version MinMsQuicVersion = new Version(2, 2, 2); private static readonly delegate* unmanaged[Cdecl] MsQuicOpenVersion; private static readonly delegate* unmanaged[Cdecl] MsQuicClose; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic_generated.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic_generated.cs index 738c2365f604f7..e81786c5fbcb7d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic_generated.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/msquic_generated.cs @@ -129,6 +129,7 @@ internal enum QUIC_STREAM_OPEN_FLAGS NONE = 0x0000, UNIDIRECTIONAL = 0x0001, ZERO_RTT = 0x0002, + DELAY_FC_UPDATES = 0x0004, } [System.Flags] diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 83073bcfab5022..91386d957c5438 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -500,6 +500,8 @@ private unsafe int HandleEventPeerStreamStarted(ref PEER_STREAM_STARTED_DATA dat stream.Dispose(); return QUIC_STATUS_SUCCESS; } + + data.Flags |= QUIC_STREAM_OPEN_FLAGS.DELAY_FC_UPDATES; return QUIC_STATUS_SUCCESS; } private unsafe int HandleEventPeerCertificateReceived(ref PEER_CERTIFICATE_RECEIVED_DATA data) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index c032f4f8a14ea3..322f47a9e8425e 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -584,6 +584,32 @@ ValueTask OpenStreamAsync(QuicConnection connection) => unidirection await serverConnection.DisposeAsync(); } + [Fact] + public async Task OpenStreamAsync_BlocksUntilAvailable_PeerClosesWritingUnidirectional() + { + QuicListenerOptions listenerOptions = new QuicListenerOptions() + { + ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), + ApplicationProtocols = new List() { ApplicationProtocol }, + ConnectionOptionsCallback = (_, _, _) => + { + var serverOptions = CreateQuicServerOptions(); + serverOptions.MaxInboundBidirectionalStreams = 1; + serverOptions.MaxInboundUnidirectionalStreams = 1; + return ValueTask.FromResult(serverOptions); + } + }; + (QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(null, listenerOptions); + + // Open one stream, second call should block + await using var stream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); + await stream.WriteAsync(new byte[64*1024], completeWrites: true); + await Assert.ThrowsAsync(() => clientConnection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional).AsTask().WaitAsync(TimeSpan.FromSeconds(1))); + + await clientConnection.DisposeAsync(); + await serverConnection.DisposeAsync(); + } + [Theory] [InlineData(false)] [InlineData(true)] @@ -622,11 +648,24 @@ ValueTask OpenStreamAsync(QuicConnection connection, CancellationTok // Close the streams, the waitTask should finish as a result. await stream.DisposeAsync(); - QuicStream newStream = await serverConnection.AcceptInboundStreamAsync(); - await newStream.DisposeAsync(); + // Drain all server streams. + while (true) + { + using var acceptCts = new CancellationTokenSource(TimeSpan.FromSeconds(0.5)); + try + { + QuicStream serverStream = await serverConnection.AcceptInboundStreamAsync(acceptCts.Token); + await serverStream.DisposeAsync(); + } + catch (OperationCanceledException) + { + // Token expired, no more streams in the server queue, exit the loop. + break; + } + } // next call should work as intended - newStream = await OpenStreamAsync(clientConnection).AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var newStream = await OpenStreamAsync(clientConnection).AsTask().WaitAsync(TimeSpan.FromSeconds(10)); await newStream.DisposeAsync(); await clientConnection.DisposeAsync(); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj b/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj index 62b1be2da62e95..18a4a8a0f8a521 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj @@ -4,6 +4,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix true + CA2252 From 7290ca630b2d139d76bb999323d89f5b7fa6af30 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 08:02:34 -0700 Subject: [PATCH 2/2] [release/7.0] Update dependencies from dotnet/xharness (#88768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/xharness build 20230621.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 7.0.0-prerelease.23309.1 -> To Version 7.0.0-prerelease.23321.1 * Remove unnecessary spacing from conflict merge --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- NuGet.config | 4 ++++ eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 6 +++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 61de9e3a631a20..0bfa9d6aaa4cc6 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "7.0.0-prerelease.23309.1", + "version": "7.0.0-prerelease.23321.1", "commands": [ "xharness" ] diff --git a/NuGet.config b/NuGet.config index 7c7c44ce2ad52c..7f2a4c72f0f142 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,6 +9,10 @@ + + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 69de1aacd5aa41..d4a22e40929e4c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -246,17 +246,17 @@ https://github.com/dotnet/linker 13a94b5bdc9d01ecd9eb2bd699bd34d597c3ec19 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 - + https://github.com/dotnet/xharness - 0627fd5c5d3d1979e3a2234280e47c149c73333a + 08db853202902978dedf7562643a5b29bebf8645 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index c2e556a4e5d3ac..bae5f15833b28f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -154,9 +154,9 @@ 1.1.0 17.4.0-preview-20220707-01 - 7.0.0-prerelease.23309.1 - 7.0.0-prerelease.23309.1 - 7.0.0-prerelease.23309.1 + 7.0.0-prerelease.23321.1 + 7.0.0-prerelease.23321.1 + 7.0.0-prerelease.23321.1 7.0.0-alpha.0.23226.5 2.4.2 1.0.0