Skip to content

Commit 827c834

Browse files
janvorlijkotas
andauthored
Remove CONTEXT_XSTATE in FaultingExceptionFrame::UpdateRegDisplay (#105569)
* Remove CONTEXT_XSTATE in FaultingExceptionFrame::UpdateRegDisplay There is a bug in updating REGDISPLAY from a faulting exception frame. The context stored in the frame can contain extended state, but we only copy the basic CONTEXT part. But we are not removing the CONTEXT_XSTATE flag. There was an issue found on arm64 Windows with SVE enabled. The context from a hardware exception contains the SVE extended state and when we resume after catch for the exception or start propagating it through native frames, the RtlRestoreContext probably uses some garbage to try to restore the extended state and ends up corrupting memory. The fix is to remove the CONTEXT_XSTATE flag from the context after we copy it to the REGDISPLAY. While we have hit this problem on Windows ARM64 with SVE only, I have made the same change for other targets that can have extended state too. Close #105483 * Move the CONTEXT_XSTATE definition to clrnt.h --------- Co-authored-by: Jan Kotas <[email protected]>
1 parent 4c3edd5 commit 827c834

File tree

5 files changed

+30
-20
lines changed

5 files changed

+30
-20
lines changed

src/coreclr/inc/clrnt.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,24 @@ RtlVirtualUnwind(
369369
IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
370370
);
371371

372+
// Mirror the XSTATE_ARM64_SVE flags from winnt.h
373+
374+
#ifndef XSTATE_ARM64_SVE
375+
#define XSTATE_ARM64_SVE (2)
376+
#endif // XSTATE_ARM64_SVE
377+
378+
#ifndef XSTATE_MASK_ARM64_SVE
379+
#define XSTATE_MASK_ARM64_SVE (1ui64 << (XSTATE_ARM64_SVE))
380+
#endif // XSTATE_MASK_ARM64_SVE
381+
382+
#ifndef CONTEXT_ARM64_XSTATE
383+
#define CONTEXT_ARM64_XSTATE (CONTEXT_ARM64 | 0x20L)
384+
#endif // CONTEXT_ARM64_XSTATE
385+
386+
#ifndef CONTEXT_XSTATE
387+
#define CONTEXT_XSTATE CONTEXT_ARM64_XSTATE
388+
#endif // CONTEXT_XSTATE
389+
372390
#endif
373391

374392
#ifdef TARGET_LOONGARCH64

src/coreclr/vm/amd64/cgenamd64.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update
231231

232232
memcpy(pRD->pCurrentContext, &m_ctx, sizeof(CONTEXT));
233233

234+
// Clear the CONTEXT_XSTATE, since the REGDISPLAY contains just plain CONTEXT structure
235+
// that cannot contain any extended state.
236+
pRD->pCurrentContext->ContextFlags &= ~CONTEXT_XSTATE;
237+
234238
pRD->ControlPC = m_ctx.Rip;
235239

236240
pRD->SP = m_ctx.Rsp;

src/coreclr/vm/arm64/stubs.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update
635635
// Copy the context to regdisplay
636636
memcpy(pRD->pCurrentContext, &m_ctx, sizeof(T_CONTEXT));
637637

638+
// Clear the CONTEXT_XSTATE, since the REGDISPLAY contains just plain CONTEXT structure
639+
// that cannot contain any extended state.
640+
pRD->pCurrentContext->ContextFlags &= ~CONTEXT_XSTATE;
641+
638642
pRD->ControlPC = ::GetIP(&m_ctx);
639643
pRD->SP = ::GetSP(&m_ctx);
640644

src/coreclr/vm/i386/cgenx86.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,10 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool update
478478

479479
memcpy(pRD->pCurrentContext, &m_ctx, sizeof(CONTEXT));
480480

481+
// Clear the CONTEXT_XSTATE, since the REGDISPLAY contains just plain CONTEXT structure
482+
// that cannot contain any extended state.
483+
pRD->pCurrentContext->ContextFlags &= ~CONTEXT_XSTATE;
484+
481485
pRD->SP = m_ctx.Esp;
482486
pRD->ControlPC = m_ctx.Eip;
483487

src/coreclr/vm/threadsuspend.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,6 @@ ThreadSuspend::SUSPEND_REASON ThreadSuspend::m_suspendReason;
2828
void* ThreadSuspend::g_returnAddressHijackTarget = NULL;
2929
#endif // TARGET_WINDOWS
3030

31-
#if defined(TARGET_ARM64)
32-
// Mirror the XSTATE_ARM64_SVE flags from winnt.h
33-
34-
#ifndef XSTATE_ARM64_SVE
35-
#define XSTATE_ARM64_SVE (2)
36-
#endif // XSTATE_ARM64_SVE
37-
38-
#ifndef XSTATE_MASK_ARM64_SVE
39-
#define XSTATE_MASK_ARM64_SVE (1ui64 << (XSTATE_ARM64_SVE))
40-
#endif // XSTATE_MASK_ARM64_SVE
41-
42-
#ifndef CONTEXT_ARM64_XSTATE
43-
#define CONTEXT_ARM64_XSTATE (CONTEXT_ARM64 | 0x20L)
44-
#endif // CONTEXT_ARM64_XSTATE
45-
46-
#ifndef CONTEXT_XSTATE
47-
#define CONTEXT_XSTATE CONTEXT_ARM64_XSTATE
48-
#endif // CONTEXT_XSTATE
49-
#endif // TARGET_ARM64
50-
5131
// If you add any thread redirection function, make sure the debugger can 1) recognize the redirection
5232
// function, and 2) retrieve the original CONTEXT. See code:Debugger.InitializeHijackFunctionAddress and
5333
// code:DacDbiInterfaceImpl.RetrieveHijackedContext.

0 commit comments

Comments
 (0)