Skip to content

Commit 7aefd27

Browse files
authored
Fix nonvolatile context restoration (#101709)
* Fix nonvolatile context restoration There is a possibility of a race between the ClrRestoreNonVolatileContext and an async signal handling (like the one we use for runtime suspension). If the signal kicks in after we've loaded Rsp, but before we jumped to the target address, the context we are loading the registers from could get overwritten by the signal handler stack. So the ClrRestoreNonVolatileContext would end up jumping into a wrong target address. The fix is to load the target address into a register before loading the Rsp and then jumping using the register. * Fix arm and x86
1 parent 30b3721 commit 7aefd27

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

src/coreclr/pal/src/arch/arm/context2.S

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,28 @@ LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT):
160160
ldr R2, [r0, #(CONTEXT_Cpsr)]
161161
msr APSR, r2
162162

163-
// Ideally, we would like to use `ldmia r0, {r0-r12, sp, lr, pc}` here,
164-
// but clang 3.6 and later, as per ARM recommendation, disallows using
165-
// Sp in the register list, and Pc and Lr simultaneously.
166-
// So we are going to use the IPC register r12 to copy Sp, Lr and Pc
167-
// which should be ok -- TODO: Is this really ok?
163+
ldr r1, [r0, #(CONTEXT_Sp)]
164+
ldr r2, [r0, #(CONTEXT_Pc)]
165+
str r2, [r1, #-4]
166+
ldr r2, [r0, #(CONTEXT_R12)]
167+
str r2, [r1, #-8]
168168
add r12, r0, CONTEXT_R0
169169
ldm r12, {r0-r11}
170-
ldr sp, [r12, #(CONTEXT_Sp - (CONTEXT_R0))]
171170
ldr lr, [r12, #(CONTEXT_Lr - (CONTEXT_R0))]
172-
ldr pc, [r12, #(CONTEXT_Pc - (CONTEXT_R0))]
171+
ldr r12, [r12, #(CONTEXT_Sp - (CONTEXT_R0))]
172+
sub r12, r12, #8
173+
mov sp, r12
174+
pop {r12, pc}
173175

174176
LOCAL_LABEL(No_Restore_CONTEXT_INTEGER):
175177

176178
ldr r2, [r0, #(CONTEXT_Cpsr)]
177179
msr APSR, r2
178180

179-
ldr sp, [r0, #(CONTEXT_Sp)]
180181
ldr lr, [r0, #(CONTEXT_Lr)]
181-
ldr pc, [r0, #(CONTEXT_Pc)]
182+
ldr r2, [r0, #(CONTEXT_Pc)]
183+
ldr sp, [r0, #(CONTEXT_Sp)]
184+
bx r2
182185

183186
LOCAL_LABEL(No_Restore_CONTEXT_CONTROL):
184187
ldr r2, [r0, #(CONTEXT_ContextFlags)]

src/coreclr/pal/src/arch/i386/context2.S

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT):
115115
movdqu xmm7, [eax + CONTEXT_Xmm7]
116116
LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS):
117117

118-
// Restore Stack
119-
mov esp, [eax + CONTEXT_Esp]
120-
121118
// Create a minimal frame
122-
push DWORD PTR [eax + CONTEXT_Eip]
119+
mov ebx, [eax + CONTEXT_Esp]
120+
mov ecx, [eax + CONTEXT_Eip]
121+
mov edx, [eax + CONTEXT_Eax]
122+
mov [ebx - 4], ecx
123+
mov [ebx - 8], edx
123124

124125
// Restore register(s)
125126
mov ebp, [eax + CONTEXT_Ebp]
@@ -128,7 +129,13 @@ LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS):
128129
mov edx, [eax + CONTEXT_Edx]
129130
mov ecx, [eax + CONTEXT_Ecx]
130131
mov ebx, [eax + CONTEXT_Ebx]
131-
mov eax, [eax + CONTEXT_Eax]
132+
133+
// Restore Stack
134+
mov eax, [eax + CONTEXT_Esp]
135+
sub eax, 8
136+
mov esp, eax
137+
138+
pop eax
132139

133140
// Resume
134141
ret

src/coreclr/vm/amd64/Context.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT, NoHandler
5151
// exception handling, iret and ret can't be used because their shadow stack enforcement would not allow that transition,
5252
// and using them would require writing to the shadow stack, which is not preferable. Instead, iret is partially
5353
// simulated.
54+
mov rax, [r10 + OFFSETOF__CONTEXT__Rip]
5455
mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp]
55-
jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip]
56+
jmp rax
5657
Done_Restore_CONTEXT_CONTROL:
5758
5859
// The function was not asked to restore the control registers so we return back to the caller

src/coreclr/vm/amd64/Context.asm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ NESTED_ENTRY ClrRestoreNonvolatileContextWorker, _TEXT
6363
mov eax, [r10 + OFFSETOF__CONTEXT__EFlags]
6464
push rax
6565
popfq
66+
mov rax, [r10 + OFFSETOF__CONTEXT__Rip]
6667
mov rsp, [r10 + OFFSETOF__CONTEXT__Rsp]
67-
jmp qword ptr [r10 + OFFSETOF__CONTEXT__Rip]
68+
jmp rax
6869
Done_Restore_CONTEXT_CONTROL:
6970
7071
; The function was not asked to restore the control registers so we return back to the caller

0 commit comments

Comments
 (0)