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  }