protectmem

package module
v0.0.0-...-e204128 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2017 License: MIT Imports: 4 Imported by: 0

README

protectmem GoDoc Build Status Coverage Status

A Golang library to allocate memory that can have access protection changed after allocation

Not intended for production

This library is not intended for producton code, it uses unsafe heavily and relies on implementation details of how slices and interfaces are represented in memory.

Documentation

Overview

Package protectmem provides functions to allocate memory that can be protected after allocation. Protecting allows removing Write access or Read access after the memory has been allocated.

This package is not intended to be used in production code, but is intended for unit tests.

Example (AllocateAndProtect)
package main

import (
	"fmt"
	"unsafe"

	"github.com/prashantv/protectmem"
)

func main() {
	type S struct {
		F1 string
		F2 string
	}

	// Allocate S using protectmem
	sAlloc := protectmem.Allocate(unsafe.Sizeof(S{}))
	sPtr := (*S)(sAlloc.Ptr())

	// sPtr can be used as a normal Go struct
	sPtr.F1 = "f1"
	sPtr.F2 = "more data"

	// Now you can protect the memory from being modified
	sAlloc.Protect(protectmem.Read)

	// Reads are fine:
	_ = sPtr.F1

	// Writes will cause a fault
	sPtr.F1 = "this will fail"

	// You can also protect from both reads and writes
	sAlloc.Protect(protectmem.None)

	// Even reads will fail.
	fmt.Println(sPtr.F1)
}
Output:

Example (AllocateSliceAndProtect)
package main

import (
	"fmt"

	"github.com/prashantv/protectmem"
)

func main() {
	var ints []int

	// Initializes ints to be a slice with 10 capacity, 0 length.
	alloc := protectmem.AllocateSlice(&ints, 10)

	for i := 0; i < cap(ints); i++ {
		ints = append(ints, i)
	}

	// Make the slice read only, can still print the slice fine.
	alloc.Protect(protectmem.Read)
	fmt.Println(ints)

	// ints cannot be written to, the following would crash
	ints[1] = 5

	// We can also protect the slice from any reads or writes
	alloc.Protect(protectmem.None)

	// Now even a read will fail
	fmt.Println(ints)
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Access

type Access int

Access returns the access level for an allocation.

const (
	None Access = (1 << iota)
	Read
	Write
)

List of different access bits that can be ORed together.

func (Access) String

func (a Access) String() string

type Allocation

type Allocation struct {
	// contains filtered or unexported fields
}

Allocation represents an allocation created by this package that can be protected.

func Allocate

func Allocate(size uintptr) *Allocation

Allocate allocates space with the specified size that can be protected in future. The size is typically specified using unsafe.Sizeof

Example
package main

import (
	"net"
	"unsafe"

	"github.com/prashantv/protectmem"
)

func main() {
	ipAlloc := protectmem.Allocate(unsafe.Sizeof(net.IPAddr{}))
	ip := (*net.IPAddr)(ipAlloc.Ptr())

	_, _ = ipAlloc, ip
}
Output:

func AllocateSlice

func AllocateSlice(slicePtr interface{}, capacity int) *Allocation

AllocateSlice allocates the specified capacity slice and modifies the given ptr.

Example
package main

import (
	"fmt"

	"github.com/prashantv/protectmem"
)

func main() {
	var strings []string
	alloc := protectmem.AllocateSlice(&strings, 100)

	_ = alloc

	fmt.Println("length", len(strings), "cap", cap(strings))
}
Output:

length 0 cap 100

func (*Allocation) Access

func (a *Allocation) Access() Access

Access returns the current access level for the page.

Example
package main

import (
	"fmt"
	"net"
	"unsafe"

	"github.com/prashantv/protectmem"
)

func main() {
	alloc := protectmem.Allocate(unsafe.Sizeof(net.IPAddr{}))

	// Access returns the permissions for the alloc.
	// By default, everything starts off with read + write.
	fmt.Println(alloc.Access())

}
Output:

read+write

func (*Allocation) Protect

func (a *Allocation) Protect(access Access)

Protect protectes the allocation with the given access settings.

Example
package main

import (
	"net"
	"unsafe"

	"github.com/prashantv/protectmem"
)

func main() {
	ipAlloc := protectmem.Allocate(unsafe.Sizeof(net.IPAddr{}))
	ip := (*net.IPAddr)(ipAlloc.Ptr())

	// Protect can be used to change the access permissions for the alloc.
	ipAlloc.Protect(protectmem.Read)

	// ip cannot be written to, any writes will crash.
	ip.Zone = "this will fail"
}
Output:

func (*Allocation) Ptr

func (a *Allocation) Ptr() unsafe.Pointer

Ptr returns an unsafe.Pointer that should be casted into the type that the user wants to use.

Example
package main

import (
	"net"
	"unsafe"

	"github.com/prashantv/protectmem"
)

func main() {
	ipAlloc := protectmem.Allocate(unsafe.Sizeof(net.IPAddr{}))

	// Ptr returns an unsafe.Pointer which can be casted into a pointer
	// of the type specified in Allocate.
	ip := (*net.IP)(ipAlloc.Ptr())

	_, _ = ipAlloc, ip
}
Output:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL