Commit a3a630b0 authored by Clément Chigot's avatar Clément Chigot Committed by Austin Clements

runtime: use mprotect in sysMap for aix/ppc64

AIX doesn't allow to mmap an already mmap address. The previous way to
deal with this behavior was to munmap before calling mmap again.
However, mprotect syscall is able to change protections on a memory
range. Thus, memory mapped by sysReserve can be remap using it. Note
that sysMap is always called with a non-nil pointer so mprotect is
always possible.

Updates: #35451

Change-Id: I1fd1e1363d9ed9eb5a8aa7c8242549bd6dad8cd0
Reviewed-on: https://go-review.googlesource.com/c/go/+/207237Reviewed-by: default avatarAustin Clements <austin@google.com>
Reviewed-by: default avatarMichael Knyszek <mknyszek@google.com>
parent 590052ba
......@@ -63,14 +63,15 @@ func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
mSysStatInc(sysStat, n)
// AIX does not allow mapping a range that is already mapped.
// So always unmap first even if it is already unmapped.
munmap(v, n)
p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
// So, call mprotect to change permissions.
// Note that sysMap is always called with a non-nil pointer
// since it transitions a Reserved memory region to Prepared,
// so mprotect is always possible.
_, err := mprotect(v, n, _PROT_READ|_PROT_WRITE)
if err == _ENOMEM {
throw("runtime: out of memory")
}
if p != v || err != 0 {
if err != 0 {
throw("runtime: cannot map pages in arena address space")
}
}
......@@ -38,6 +38,7 @@ var (
//go:cgo_import_dynamic libc_madvise madvise "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_malloc malloc "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_mmap mmap "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_mprotect mprotect "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_munmap munmap "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_open open "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_pipe pipe "libc.a/shr_64.o"
......@@ -77,6 +78,7 @@ var (
//go:linkname libc_madvise libc_madvise
//go:linkname libc_malloc libc_malloc
//go:linkname libc_mmap libc_mmap
//go:linkname libc_mprotect libc_mprotect
//go:linkname libc_munmap libc_munmap
//go:linkname libc_open libc_open
//go:linkname libc_pipe libc_pipe
......@@ -118,6 +120,7 @@ var (
libc_madvise,
libc_malloc,
libc_mmap,
libc_mprotect,
libc_munmap,
libc_open,
libc_pipe,
......@@ -458,6 +461,15 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un
return unsafe.Pointer(r), int(err0)
}
//go:nosplit
func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (unsafe.Pointer, int) {
r, err0 := syscall3(&libc_mprotect, uintptr(addr), uintptr(n), uintptr(prot))
if r == ^uintptr(0) {
return nil, int(err0)
}
return unsafe.Pointer(r), int(err0)
}
//go:nosplit
func munmap(addr unsafe.Pointer, n uintptr) {
r, err := syscall2(&libc_munmap, uintptr(addr), uintptr(n))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment