github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/safecopy/sighandler_amd64.s (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "textflag.h" 16 17 // The signals handled by sigHandler. 18 #define SIGBUS 7 19 #define SIGSEGV 11 20 21 // Offsets to the registers in context->uc_mcontext.gregs[]. 22 #define REG_RDI 0x68 23 #define REG_RAX 0x90 24 #define REG_IP 0xa8 25 26 // Offset to the si_addr field of siginfo. 27 #define SI_CODE 0x08 28 #define SI_ADDR 0x10 29 30 // signalHandler is the signal handler for SIGSEGV and SIGBUS signals. It must 31 // not be set up as a handler to any other signals. 32 // 33 // If the instruction causing the signal is within a safecopy-protected 34 // function, the signal is handled such that execution resumes in the 35 // appropriate fault handling stub with AX containing the faulting address and 36 // DI containing the signal number. Otherwise control is transferred to the 37 // previously configured signal handler (savedSigSegvHandler or 38 // savedSigBusHandler). 39 // 40 // This function cannot be written in go because it runs whenever a signal is 41 // received by the thread (preempting whatever was running), which includes when 42 // garbage collector has stopped or isn't expecting any interactions (like 43 // barriers). 44 // 45 // The arguments are the following: 46 // DI - The signal number. 47 // SI - Pointer to siginfo_t structure. 48 // DX - Pointer to ucontext structure. 49 TEXT ·signalHandler(SB),NOSPLIT|NOFRAME,$0 50 // Check if the signal is from the kernel. 51 MOVQ $0x0, CX 52 CMPL CX, SI_CODE(SI) 53 JGE original_handler 54 55 // Check if RIP is within the area we care about. 56 MOVQ REG_IP(DX), CX 57 CMPQ CX, ·memcpyBegin(SB) 58 JB not_memcpy 59 CMPQ CX, ·memcpyEnd(SB) 60 JAE not_memcpy 61 62 // Modify the context such that execution will resume in the fault 63 // handler. 64 LEAQ handleMemcpyFault(SB), CX 65 JMP handle_fault 66 67 not_memcpy: 68 CMPQ CX, ·memclrBegin(SB) 69 JB not_memclr 70 CMPQ CX, ·memclrEnd(SB) 71 JAE not_memclr 72 73 LEAQ handleMemclrFault(SB), CX 74 JMP handle_fault 75 76 not_memclr: 77 CMPQ CX, ·swapUint32Begin(SB) 78 JB not_swapuint32 79 CMPQ CX, ·swapUint32End(SB) 80 JAE not_swapuint32 81 82 LEAQ handleSwapUint32Fault(SB), CX 83 JMP handle_fault 84 85 not_swapuint32: 86 CMPQ CX, ·swapUint64Begin(SB) 87 JB not_swapuint64 88 CMPQ CX, ·swapUint64End(SB) 89 JAE not_swapuint64 90 91 LEAQ handleSwapUint64Fault(SB), CX 92 JMP handle_fault 93 94 not_swapuint64: 95 CMPQ CX, ·compareAndSwapUint32Begin(SB) 96 JB not_casuint32 97 CMPQ CX, ·compareAndSwapUint32End(SB) 98 JAE not_casuint32 99 100 LEAQ handleCompareAndSwapUint32Fault(SB), CX 101 JMP handle_fault 102 103 not_casuint32: 104 CMPQ CX, ·loadUint32Begin(SB) 105 JB not_loaduint32 106 CMPQ CX, ·loadUint32End(SB) 107 JAE not_loaduint32 108 109 LEAQ handleLoadUint32Fault(SB), CX 110 JMP handle_fault 111 112 not_loaduint32: 113 CMPQ CX, ·checkXstateBegin(SB) 114 JB not_checkXstate 115 CMPQ CX, ·checkXstateEnd(SB) 116 JAE not_checkXstate 117 118 LEAQ handleCheckXstateFault(SB), CX 119 JMP handle_fault 120 not_checkXstate: 121 original_handler: 122 // Jump to the previous signal handler, which is likely the golang one. 123 XORQ CX, CX 124 MOVQ ·savedSigBusHandler(SB), AX 125 CMPL DI, $SIGSEGV 126 CMOVQEQ ·savedSigSegVHandler(SB), AX 127 JMP AX 128 129 handle_fault: 130 // Entered with the address of the fault handler in RCX; store it in 131 // RIP. 132 MOVQ CX, REG_IP(DX) 133 134 // Store the faulting address in RAX. 135 MOVQ SI_ADDR(SI), CX 136 MOVQ CX, REG_RAX(DX) 137 138 // Store the signal number in EDI. 139 MOVL DI, REG_RDI(DX) 140 141 RET 142 143 // func addrOfSignalHandler() uintptr 144 TEXT ·addrOfSignalHandler(SB), $0-8 145 MOVQ $·signalHandler(SB), AX 146 MOVQ AX, ret+0(FP) 147 RET