github.com/Rookout/GoSDK@v0.1.48/pkg/services/protector/mprotect_linux.go (about) 1 //go:build !darwin 2 // +build !darwin 3 4 package protector 5 6 import ( 7 "bufio" 8 "os" 9 "strconv" 10 "strings" 11 "syscall" 12 13 "github.com/Rookout/GoSDK/pkg/logger" 14 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 15 ) 16 17 type memoryRegion struct { 18 StartAddr uint64 19 EndAddr uint64 20 Permissions int 21 } 22 23 func parseMapsLine(line string) (*memoryRegion, rookoutErrors.RookoutError) { 24 fields := strings.Fields(line) 25 if len(fields) < 5 { 26 return nil, rookoutErrors.NewInvalidProcMapsLine(line) 27 } 28 29 addrFields := strings.Split(fields[0], "-") 30 if len(addrFields) != 2 { 31 return nil, rookoutErrors.NewInvalidProcMapsAddresses(line, fields[0]) 32 } 33 startAddr, err := strconv.ParseUint(addrFields[0], 16, 64) 34 if err != nil { 35 return nil, rookoutErrors.NewInvalidProcMapsStartAddress(line, addrFields[0], err) 36 } 37 endAddr, err := strconv.ParseUint(addrFields[1], 16, 64) 38 if err != nil { 39 return nil, rookoutErrors.NewInvalidProcMapsEndAddress(line, addrFields[1], err) 40 } 41 42 var permissions int 43 if strings.Contains(fields[1], "r") { 44 permissions |= syscall.PROT_READ 45 } 46 if strings.Contains(fields[1], "w") { 47 permissions |= syscall.PROT_WRITE 48 } 49 if strings.Contains(fields[1], "x") { 50 permissions |= syscall.PROT_EXEC 51 } 52 53 return &memoryRegion{ 54 StartAddr: startAddr, 55 EndAddr: endAddr, 56 Permissions: permissions, 57 }, nil 58 } 59 60 func GetMemoryProtection(addr uint64, size uint64) (int, rookoutErrors.RookoutError) { 61 mapsFile, err := os.Open("/proc/self/maps") 62 if err != nil { 63 return 0, rookoutErrors.NewFailedToOpenProcMapsFile(err) 64 } 65 defer mapsFile.Close() 66 startAddr := addr 67 endAddr := addr + size 68 69 var permissions int 70 scanner := bufio.NewScanner(mapsFile) 71 for scanner.Scan() { 72 memoryRegion, err := parseMapsLine(scanner.Text()) 73 if err != nil { 74 logger.Logger().WithError(err).Warning("Failed to parse maps line, continuing") 75 } 76 77 if startAddr < memoryRegion.EndAddr && memoryRegion.StartAddr < endAddr { 78 permissions |= memoryRegion.Permissions 79 } else if endAddr < memoryRegion.StartAddr { 80 81 break 82 } 83 } 84 return permissions, nil 85 } 86 87 func ChangeMemoryProtection(start uintptr, end uintptr, prot int) rookoutErrors.RookoutError { 88 _, _, errno := syscall.Syscall(syscall.SYS_MPROTECT, start, end-start, uintptr(prot)) 89 if errno != 0 { 90 return rookoutErrors.NewMprotectFailed(start, int(end-start), prot, errno.Error()) 91 } 92 return nil 93 }