Skip to content

[RuntimeAsync] Sometimes GS cookie check uses the same register as the continuation return. #119796

@VSadov

Description

@VSadov

Observed while enabling rt async in Libraires partition - #119432

This may be x64-specific.

In the TTD trace I see the following asm code.
It happens somewhere around
private async ValueTask FinishConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default)

I am not sure if the asm actually belongs to that method or to something that was inlined, or to some stub/helper,
but this is where we end up corrupting the continuation, which would be returned in rcx.

00007ffa`97bb6606 488b85d0fbffff       mov     rax, qword ptr [rbp-430h]      // loading the continuation temp, I assume
00007ffa`97bb660d 488bc8               mov     rcx, rax                       // continuation is in its register
00007ffa`97bb6610 48b978563412f0debc9a mov     rcx, 9ABCDEF012345678h         // loading GS cookie (this is a debug codegen, thus the cookie is a known const)
00007ffa`97bb661a 48394de8             cmp     qword ptr [rbp-18h], rcx       //     the load above trashes the continuation result, eventually we crash
00007ffa`97bb661e 7405                 je      00007FFA97BB6625
00007ffa`97bb6620 e8db969a5c           call    coreclr!JIT_FailFast (7ffaf455fd00)
00007ffa`97bb6625 90                   nop     
00007ffa`97bb6626 c5f877               vzeroupper 
00007ffa`97bb6629 4881c4b0040000       add     rsp, 4B0h
00007ffa`97bb6630 5e                   pop     rsi
00007ffa`97bb6631 5f                   pop     rdi
00007ffa`97bb6632 5d                   pop     rbp
00007ffa`97bb6633 c3                   ret 

Then we crash as in:

  Fatal error.
  System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
     at System.Runtime.CompilerServices.AsyncHelpers.FinalizeTaskReturningThunk(System.Runtime.CompilerServices.Continuation)
     at System.Runtime.CompilerServices.AsyncHelpers.FinalizeValueTaskReturningThunk(System.Runtime.CompilerServices.Continuation)
     at System.Net.Quic.QuicConnection.FinishConnectAsync(System.Net.Quic.QuicClientConnectionOptions, System.Threading.CancellationToken)
     at System.Net.Quic.QuicConnection.<ConnectAsync>g__StartConnectAsync|2_0(System.Net.Quic.QuicClientConnectionOptions, System.Threading.CancellationToken)
     at System.Net.Quic.QuicConnection.<ConnectAsync>g__StartConnectAsync|2_0(System.Net.Quic.QuicClientConnectionOptions, System.Threading.CancellationToken)
     at System.Net.Quic.QuicConnection.ConnectAsync(System.Net.Quic.QuicClientConnectionOptions, System.Threading.CancellationToken)
     at System.Net.Quic.Tests.QuicTestBase.CreateQuicConnection(System.Net.Quic.QuicClientConnectionOptions)
     at System.Net.Quic.Tests.QuicTestBase.CreateConnectedQuicConnection(System.Net.Quic.QuicClientConnectionOptions, System.Net.Quic.QuicListener)
     at System.Net.Quic.Tests.QuicTestBase.CreateConnectedQuicConnection(System.Net.Quic.QuicClientConnectionOptions, System.Net.Quic.QuicListener)
     at System.Net.Quic.Tests.QuicTestBase.CreateConnectedQuicConnection(System.Net.Quic.QuicListener)
     at System.Net.Quic.Tests.QuicTestBase.CreateConnectedQuicConnection(System.Net.Quic.QuicListener)
     at System.Net.Quic.Tests.QuicTestBase.RunClientServer(System.Func`2<System.Net.Quic.QuicConnection,System.Threading.Tasks.Task>, System.Func`2<System.Net.Quic.QuicConnection,System.Threading.Tasks.Task>, Int32, Int32, System.Net.Quic.QuicListenerOptions)
     at System.Net.Quic.Tests.QuicTestBase.RunStreamClientServer(System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, Boolean, Int32, Int32)
     at System.Net.Quic.Tests.QuicTestBase.RunStreamClientServer(System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, Boolean, Int32, Int32)
     at System.Net.Quic.Tests.QuicTestBase.RunBidirectionalClientServer(System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, Int32, Int32)
     at System.Net.Quic.Tests.QuicTestBase.RunBidirectionalClientServer(System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, System.Func`2<System.Net.Quic.QuicStream,System.Threading.Tasks.Task>, Int32, Int32)
     at System.Net.Quic.Tests.MsQuicTests.Read_ReadsCompleted_ReportedBeforeReturning0()

An approximate fix is in:

aa745d1

(just make the GS check always use REG_ARG_1)

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIruntime-async

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions