Skip to content

Commit a3a630b

Browse files
Helflymaclements
authored andcommitted
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/+/207237 Reviewed-by: Austin Clements <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 590052b commit a3a630b

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

src/runtime/mem_aix.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,15 @@ func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
6363
mSysStatInc(sysStat, n)
6464

6565
// AIX does not allow mapping a range that is already mapped.
66-
// So always unmap first even if it is already unmapped.
67-
munmap(v, n)
68-
p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
69-
66+
// So, call mprotect to change permissions.
67+
// Note that sysMap is always called with a non-nil pointer
68+
// since it transitions a Reserved memory region to Prepared,
69+
// so mprotect is always possible.
70+
_, err := mprotect(v, n, _PROT_READ|_PROT_WRITE)
7071
if err == _ENOMEM {
7172
throw("runtime: out of memory")
7273
}
73-
if p != v || err != 0 {
74+
if err != 0 {
7475
throw("runtime: cannot map pages in arena address space")
7576
}
7677
}

src/runtime/os2_aix.go

+12
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var (
3838
//go:cgo_import_dynamic libc_madvise madvise "libc.a/shr_64.o"
3939
//go:cgo_import_dynamic libc_malloc malloc "libc.a/shr_64.o"
4040
//go:cgo_import_dynamic libc_mmap mmap "libc.a/shr_64.o"
41+
//go:cgo_import_dynamic libc_mprotect mprotect "libc.a/shr_64.o"
4142
//go:cgo_import_dynamic libc_munmap munmap "libc.a/shr_64.o"
4243
//go:cgo_import_dynamic libc_open open "libc.a/shr_64.o"
4344
//go:cgo_import_dynamic libc_pipe pipe "libc.a/shr_64.o"
@@ -77,6 +78,7 @@ var (
7778
//go:linkname libc_madvise libc_madvise
7879
//go:linkname libc_malloc libc_malloc
7980
//go:linkname libc_mmap libc_mmap
81+
//go:linkname libc_mprotect libc_mprotect
8082
//go:linkname libc_munmap libc_munmap
8183
//go:linkname libc_open libc_open
8284
//go:linkname libc_pipe libc_pipe
@@ -118,6 +120,7 @@ var (
118120
libc_madvise,
119121
libc_malloc,
120122
libc_mmap,
123+
libc_mprotect,
121124
libc_munmap,
122125
libc_open,
123126
libc_pipe,
@@ -458,6 +461,15 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un
458461
return unsafe.Pointer(r), int(err0)
459462
}
460463

464+
//go:nosplit
465+
func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (unsafe.Pointer, int) {
466+
r, err0 := syscall3(&libc_mprotect, uintptr(addr), uintptr(n), uintptr(prot))
467+
if r == ^uintptr(0) {
468+
return nil, int(err0)
469+
}
470+
return unsafe.Pointer(r), int(err0)
471+
}
472+
461473
//go:nosplit
462474
func munmap(addr unsafe.Pointer, n uintptr) {
463475
r, err := syscall2(&libc_munmap, uintptr(addr), uintptr(n))

0 commit comments

Comments
 (0)