github.com/Rookout/GoSDK@v0.1.48/pkg/services/safe_hook_installer/safe_hook_installer.go (about) 1 package safe_hook_installer 2 3 import ( 4 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 5 "github.com/Rookout/GoSDK/pkg/services/callstack" 6 "github.com/Rookout/GoSDK/pkg/services/protector" 7 "github.com/Rookout/GoSDK/pkg/services/safe_hook_validator" 8 "github.com/Rookout/GoSDK/pkg/services/suspender" 9 ) 10 11 type HookManager interface { 12 GetFunctionType(functionEntry uint64, functionEnd uint64) (safe_hook_validator.FunctionType, error) 13 GetDangerZoneStartAddress() uint64 14 GetDangerZoneEndAddress() uint64 15 } 16 17 type SafeHookInstallerCreator func(functionEntry, functionEnd uint64, stateID int, hookWriter *HookWriter, 18 nativeApi HookManager, goroutineSuspender suspender.Suspender, 19 stb callstack.IStackTraceBuffer, validatorFactory safe_hook_validator.ValidatorFactory) (SafeHookInstaller, error) 20 21 type SafeHookInstaller interface { 22 InstallHook() (int, rookoutErrors.RookoutError) 23 } 24 25 type RealSafeHookInstaller struct { 26 goroutineSuspender suspender.Suspender 27 stb callstack.IStackTraceBuffer 28 validator safe_hook_validator.Validator 29 hookWriter *HookWriter 30 } 31 32 type HookWriter struct { 33 Hook []byte 34 HookAddr uintptr 35 originalMemoryProtection int 36 hookPageAlignedStart uintptr 37 hookPageAlignedEnd uintptr 38 } 39 40 func NewHookWriter(hookAddr uintptr, hook []byte) *HookWriter { 41 42 hookPageAlignedStart := protector.GetPageStart(hookAddr) 43 hookPageAlignedEnd := protector.GetPageEnd(hookAddr + uintptr(len(hook)) - 1) 44 45 return &HookWriter{ 46 hookPageAlignedStart: hookPageAlignedStart, 47 hookPageAlignedEnd: hookPageAlignedEnd, 48 Hook: hook, 49 HookAddr: hookAddr, 50 } 51 } 52 53 func NewSafeHookInstaller(functionEntry, functionEnd uint64, stateID int, 54 hookWriter *HookWriter, hookManager HookManager, goroutineSuspender suspender.Suspender, 55 stb callstack.IStackTraceBuffer, validatorFactory safe_hook_validator.ValidatorFactory) (SafeHookInstaller, error) { 56 shi := &RealSafeHookInstaller{goroutineSuspender: goroutineSuspender, stb: stb, hookWriter: hookWriter} 57 err := shi.initValidator(hookManager, functionEntry, functionEnd, validatorFactory) 58 if err != nil { 59 return nil, err 60 } 61 return shi, nil 62 } 63 64 func (s *RealSafeHookInstaller) InstallHook() (n int, err rookoutErrors.RookoutError) { 65 66 var ok bool 67 var validationRes safe_hook_validator.ValidationErrorFlags 68 69 s.goroutineSuspender.StopAll() 70 n, ok = s.stb.FillStackTraces() 71 if !ok { 72 s.goroutineSuspender.ResumeAll() 73 return n, rookoutErrors.NewFailedToCollectGoroutinesInfo(n) 74 } 75 76 validationRes = s.validator.Validate(s.stb) 77 if validationRes != safe_hook_validator.NoError { 78 s.goroutineSuspender.ResumeAll() 79 return n, rookoutErrors.NewUnsafeToInstallHook(validationRes.String()) 80 } 81 82 errno := s.hookWriter.write() 83 if errno != 0 { 84 s.goroutineSuspender.ResumeAll() 85 return n, rookoutErrors.NewFailedToWriteBytes(errno) 86 } 87 s.goroutineSuspender.ResumeAll() 88 return n, nil 89 } 90 91 func (s *RealSafeHookInstaller) initValidator(hookManager HookManager, functionEntry, functionEnd uint64, 92 validatorFactory safe_hook_validator.ValidatorFactory) error { 93 funcType, err := hookManager.GetFunctionType(functionEntry, functionEnd) 94 if err != nil { 95 return err 96 } 97 98 dangerZoneStart := hookManager.GetDangerZoneStartAddress() 99 dangerZoneEnd := hookManager.GetDangerZoneEndAddress() 100 101 functionRange := safe_hook_validator.AddressRange{Start: uintptr(functionEntry), End: uintptr(functionEnd)} 102 dangerRange := safe_hook_validator.AddressRange{Start: uintptr(dangerZoneStart), End: uintptr(dangerZoneEnd)} 103 s.validator, err = validatorFactory.GetValidator(funcType, functionRange, dangerRange) 104 if err != nil { 105 return err 106 } 107 return nil 108 }