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  }