github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/safecopy/safecopy.go (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 // Package safecopy provides an efficient implementation of functions to access 16 // memory that may result in SIGSEGV or SIGBUS being sent to the accessor. 17 package safecopy 18 19 import ( 20 "fmt" 21 "runtime" 22 23 "golang.org/x/sys/unix" 24 "github.com/SagerNet/gvisor/pkg/syserror" 25 ) 26 27 // SegvError is returned when a safecopy function receives SIGSEGV. 28 type SegvError struct { 29 // Addr is the address at which the SIGSEGV occurred. 30 Addr uintptr 31 } 32 33 // Error implements error.Error. 34 func (e SegvError) Error() string { 35 return fmt.Sprintf("SIGSEGV at %#x", e.Addr) 36 } 37 38 // BusError is returned when a safecopy function receives SIGBUS. 39 type BusError struct { 40 // Addr is the address at which the SIGBUS occurred. 41 Addr uintptr 42 } 43 44 // Error implements error.Error. 45 func (e BusError) Error() string { 46 return fmt.Sprintf("SIGBUS at %#x", e.Addr) 47 } 48 49 // AlignmentError is returned when a safecopy function is passed an address 50 // that does not meet alignment requirements. 51 type AlignmentError struct { 52 // Addr is the invalid address. 53 Addr uintptr 54 55 // Alignment is the required alignment. 56 Alignment uintptr 57 } 58 59 // Error implements error.Error. 60 func (e AlignmentError) Error() string { 61 return fmt.Sprintf("address %#x is not aligned to a %d-byte boundary", e.Addr, e.Alignment) 62 } 63 64 var ( 65 // The begin and end addresses below are for the functions that are 66 // checked by the signal handler. 67 memcpyBegin uintptr 68 memcpyEnd uintptr 69 memclrBegin uintptr 70 memclrEnd uintptr 71 swapUint32Begin uintptr 72 swapUint32End uintptr 73 swapUint64Begin uintptr 74 swapUint64End uintptr 75 compareAndSwapUint32Begin uintptr 76 compareAndSwapUint32End uintptr 77 loadUint32Begin uintptr 78 loadUint32End uintptr 79 80 // savedSigSegVHandler is a pointer to the SIGSEGV handler that was 81 // configured before we replaced it with our own. We still call into it 82 // when we get a SIGSEGV that is not interesting to us. 83 savedSigSegVHandler uintptr 84 85 // same a above, but for SIGBUS signals. 86 savedSigBusHandler uintptr 87 ) 88 89 // signalHandler is our replacement signal handler for SIGSEGV and SIGBUS 90 // signals. 91 func signalHandler() 92 93 // addrOfSignalHandler returns the start address of signalHandler. 94 // 95 // See comment on addrOfMemcpy for more details. 96 func addrOfSignalHandler() uintptr 97 98 // FindEndAddress returns the end address (one byte beyond the last) of the 99 // function that contains the specified address (begin). 100 func FindEndAddress(begin uintptr) uintptr { 101 f := runtime.FuncForPC(begin) 102 if f != nil { 103 for p := begin; ; p++ { 104 g := runtime.FuncForPC(p) 105 if f != g { 106 return p 107 } 108 } 109 } 110 return begin 111 } 112 113 // initializeAddresses initializes the addresses used by the signal handler. 114 func initializeAddresses() { 115 // The following functions are written in assembly language, so they won't 116 // be inlined by the existing compiler/linker. Tests will fail if this 117 // assumption is violated. 118 memcpyBegin = addrOfMemcpy() 119 memcpyEnd = FindEndAddress(memcpyBegin) 120 memclrBegin = addrOfMemclr() 121 memclrEnd = FindEndAddress(memclrBegin) 122 swapUint32Begin = addrOfSwapUint32() 123 swapUint32End = FindEndAddress(swapUint32Begin) 124 swapUint64Begin = addrOfSwapUint64() 125 swapUint64End = FindEndAddress(swapUint64Begin) 126 compareAndSwapUint32Begin = addrOfCompareAndSwapUint32() 127 compareAndSwapUint32End = FindEndAddress(compareAndSwapUint32Begin) 128 loadUint32Begin = addrOfLoadUint32() 129 loadUint32End = FindEndAddress(loadUint32Begin) 130 } 131 132 func init() { 133 initializeAddresses() 134 if err := ReplaceSignalHandler(unix.SIGSEGV, addrOfSignalHandler(), &savedSigSegVHandler); err != nil { 135 panic(fmt.Sprintf("Unable to set handler for SIGSEGV: %v", err)) 136 } 137 if err := ReplaceSignalHandler(unix.SIGBUS, addrOfSignalHandler(), &savedSigBusHandler); err != nil { 138 panic(fmt.Sprintf("Unable to set handler for SIGBUS: %v", err)) 139 } 140 syserror.AddErrorUnwrapper(func(e error) (unix.Errno, bool) { 141 switch e.(type) { 142 case SegvError, BusError, AlignmentError: 143 return unix.EFAULT, true 144 default: 145 return 0, false 146 } 147 }) 148 }