Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AIX support #11

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions memcall_aix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// +build aix

package memcall

import (
"errors"
"fmt"

"golang.org/x/sys/unix"
)

// Lock is a wrapper for mlock(2).
func Lock(b []byte) error {
if err := unix.Mlock(b); err != nil {
if errors.Is(err, unix.EPERM) {
// per mlock(2): The calling process must have the root user authority to use this subroutine.
return fmt.Errorf("<memcall> could not acquire lock on %p, do you have PV_ROOT? [Err: %s]", _getStartPtr(b), err)
} else {
return fmt.Errorf("<memcall> could not acquire lock on %p, limit reached? [Err: %s]", _getStartPtr(b), err)
}
}

return nil
}

// Unlock is a wrapper for munlock(2).
func Unlock(b []byte) error {
if err := unix.Munlock(b); err != nil {
if errors.Is(err, unix.EPERM) {
// per munlock(2): The calling process must have the root user authority to use this subroutine.
return fmt.Errorf("<memcall> could not free lock on %p, do you have PV_ROOT? [Err: %s]", _getStartPtr(b), err)
} else {
return fmt.Errorf("<memcall> could not free lock on %p [Err: %s]", _getStartPtr(b), err)
}
}

return nil
}

// Alloc allocates a byte slice of length n and returns it.
func Alloc(n int) ([]byte, error) {
// Allocate the memory.
b, err := unix.Mmap(-1, 0, n, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANON)
if err != nil {
return nil, fmt.Errorf("<memcall> could not allocate [Err: %s]", err)
}

// Wipe it just in case there is some remnant data.
wipe(b)

// Return the allocated memory.
return b, nil
}

// Free deallocates the byte slice specified.
func Free(b []byte) error {
// Make the memory region readable and writable.
if err := Protect(b, ReadWrite()); err != nil {
return err
}

// Wipe the memory region in case of remnant data.
wipe(b)

// Free the memory back to the kernel.
if err := unix.Munmap(b); err != nil {
return fmt.Errorf("<memcall> could not deallocate %p [Err: %s]", _getStartPtr(b), err)
}

return nil
}

// Protect modifies the protection state for a specified byte slice.
func Protect(b []byte, mpf MemoryProtectionFlag) error {
var prot int
if mpf.flag == ReadWrite().flag {
prot = unix.PROT_READ | unix.PROT_WRITE
} else if mpf.flag == ReadOnly().flag {
prot = unix.PROT_READ
} else if mpf.flag == NoAccess().flag {
prot = unix.PROT_NONE
} else {
return errors.New(ErrInvalidFlag)
}

// Change the protection value of the byte slice.
if err := unix.Mprotect(b, prot); err != nil {
return fmt.Errorf("<memcall> could not set %d on %p [Err: %s]", prot, _getStartPtr(b), err)
}

return nil
}

// DisableCoreDumps disables core dumps on Unix systems.
func DisableCoreDumps() error {
// Disable core dumps.
if err := unix.Setrlimit(unix.RLIMIT_CORE, &unix.Rlimit{Cur: 0, Max: 0}); err != nil {
return fmt.Errorf("<memcall> could not set rlimit [Err: %s]", err)
}

return nil
}
2 changes: 1 addition & 1 deletion memcall_unix.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !windows,!darwin,!openbsd,!freebsd
// +build !windows,!darwin,!openbsd,!freebsd,!aix

package memcall

Expand Down