mirror of
https://github.com/golang/go
synced 2024-11-17 11:14:46 -07:00
runtime: support control flow guard on windows/amd64
The stack pointer must lie within system stack limits when Control Flow Guard (CFG) is enabled on Windows. This CL updates runtime.sigtramp to honor this restriction by porting some code from the windows/arm64 version, which already supports CFG. Fixes #53560 Change-Id: I7f88f9ae788b2bac38aac898b2567f1bea62f8f3 Reviewed-on: https://go-review.googlesource.com/c/go/+/437559 Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
7abc8a2e33
commit
5c0d314adc
@ -116,6 +116,7 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
// Make stack space for the rest of the function.
|
||||
ADJSP $48
|
||||
|
||||
MOVQ CX, R13 // save exception address
|
||||
MOVQ AX, R15 // save handler address
|
||||
|
||||
// find g
|
||||
@ -153,8 +154,8 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOVQ DI, SP
|
||||
|
||||
g0:
|
||||
MOVQ 0(CX), BX // ExceptionRecord*
|
||||
MOVQ 8(CX), CX // Context*
|
||||
MOVQ 0(R13), BX // ExceptionRecord*
|
||||
MOVQ 8(R13), CX // Context*
|
||||
MOVQ BX, 0(SP)
|
||||
MOVQ CX, 8(SP)
|
||||
MOVQ DX, 16(SP)
|
||||
@ -162,6 +163,8 @@ g0:
|
||||
// AX is set to report result back to Windows
|
||||
MOVL 24(SP), AX
|
||||
|
||||
MOVQ SP, DI // save g0 SP
|
||||
|
||||
// switch back to original stack and g
|
||||
// no-op if we never left.
|
||||
MOVQ 40(SP), SP
|
||||
@ -169,12 +172,54 @@ g0:
|
||||
get_tls(BP)
|
||||
MOVQ DX, g(BP)
|
||||
|
||||
// if return value is CONTINUE_SEARCH, do not set up control
|
||||
// flow guard workaround.
|
||||
CMPQ AX, $0
|
||||
JEQ done
|
||||
|
||||
// Check if we need to set up the control flow guard workaround.
|
||||
// On Windows, the stack pointer in the context must lie within
|
||||
// system stack limits when we resume from exception.
|
||||
// Store the resume SP and PC in alternate registers
|
||||
// and return to sigresume on the g0 stack.
|
||||
// sigresume makes no use of the stack at all,
|
||||
// loading SP from R8 and jumping to R9.
|
||||
// Note that smashing R8 and R9 is only safe because we know sigpanic
|
||||
// will not actually return to the original frame, so the registers
|
||||
// are effectively dead. But this does mean we can't use the
|
||||
// same mechanism for async preemption.
|
||||
MOVQ 8(R13), CX
|
||||
MOVQ $sigresume<>(SB), BX
|
||||
CMPQ BX, context_rip(CX)
|
||||
JEQ done // do not clobber saved SP/PC
|
||||
|
||||
// Save resume SP and PC into R8, R9.
|
||||
MOVQ context_rsp(CX), BX
|
||||
MOVQ BX, context_r8(CX)
|
||||
MOVQ context_rip(CX), BX
|
||||
MOVQ BX, context_r9(CX)
|
||||
|
||||
// Set up context record to return to sigresume on g0 stack
|
||||
MOVD DI, BX
|
||||
MOVD BX, context_rsp(CX)
|
||||
MOVD $sigresume<>(SB), BX
|
||||
MOVD BX, context_rip(CX)
|
||||
|
||||
done:
|
||||
ADJSP $-48
|
||||
POP_REGS_HOST_TO_ABI0()
|
||||
|
||||
RET
|
||||
|
||||
// Trampoline to resume execution from exception handler.
|
||||
// This is part of the control flow guard workaround.
|
||||
// It switches stacks and jumps to the continuation address.
|
||||
// R8 and R9 are set above at the end of sigtramp<>
|
||||
// in the context that starts executing at sigresume<>.
|
||||
TEXT sigresume<>(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVQ R8, SP
|
||||
JMP R9
|
||||
|
||||
TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVQ $runtime·exceptionhandler(SB), AX
|
||||
JMP sigtramp<>(SB)
|
||||
|
Loading…
Reference in New Issue
Block a user