summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sing <joel@sing.id.au>2018-12-18 03:33:25 +1100
committerBrad Fitzpatrick <bradfitz@golang.org>2018-12-18 01:43:14 +0000
commitbdd4b9503e47c2c38a9d0a9bb2f5d95ec5ff8ef6 (patch)
tree0417a4460d300c920d06a88b5a4603983f58b689
parent182bdbb1e1d62fe53f8386e7b02c7738898d373b (diff)
downloadgo-git-release-branch.go1.4.tar.gz
[release-branch.go1.4] runtime: mark stacks with MAP_STACK on openbsdrelease-branch.go1.4
OpenBSD 6.4+ requires that stack regions be marked with MAP_STACK. MAP_STACK is permitted (but is a no-op) on OpenBSD 6.3. Change-Id: I8118f27e6a0feb97ae570cbc8aad461ec20676fa Reviewed-on: https://go-review.googlesource.com/c/154477 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r--src/runtime/defs_openbsd_386.h1
-rw-r--r--src/runtime/defs_openbsd_amd64.h1
-rw-r--r--src/runtime/malloc.h2
-rw-r--r--src/runtime/mem_openbsd.c23
-rw-r--r--src/runtime/os_openbsd.c5
-rw-r--r--src/runtime/stack.c12
6 files changed, 43 insertions, 1 deletions
diff --git a/src/runtime/defs_openbsd_386.h b/src/runtime/defs_openbsd_386.h
index 6b77e0084a..c4b43ae2c8 100644
--- a/src/runtime/defs_openbsd_386.h
+++ b/src/runtime/defs_openbsd_386.h
@@ -14,6 +14,7 @@ enum {
MAP_ANON = 0x1000,
MAP_PRIVATE = 0x2,
MAP_FIXED = 0x10,
+ MAP_STACK = 0x4000,
MADV_FREE = 0x6,
diff --git a/src/runtime/defs_openbsd_amd64.h b/src/runtime/defs_openbsd_amd64.h
index 761e8e47df..263bfeb992 100644
--- a/src/runtime/defs_openbsd_amd64.h
+++ b/src/runtime/defs_openbsd_amd64.h
@@ -14,6 +14,7 @@ enum {
MAP_ANON = 0x1000,
MAP_PRIVATE = 0x2,
MAP_FIXED = 0x10,
+ MAP_STACK = 0x4000,
MADV_FREE = 0x6,
diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h
index adb8d3d677..f19751a0c5 100644
--- a/src/runtime/malloc.h
+++ b/src/runtime/malloc.h
@@ -197,6 +197,8 @@ struct MLink
// if accessed. Used only for debugging the runtime.
void* runtime·sysAlloc(uintptr nbytes, uint64 *stat);
+void runtime·sysMarkStack(void *v, uintptr nbytes);
+void runtime·sysUnmarkStack(void *v, uintptr nbytes);
void runtime·SysFree(void *v, uintptr nbytes, uint64 *stat);
void runtime·SysUnused(void *v, uintptr nbytes);
void runtime·SysUsed(void *v, uintptr nbytes);
diff --git a/src/runtime/mem_openbsd.c b/src/runtime/mem_openbsd.c
index 31820e5170..ac3a2a565a 100644
--- a/src/runtime/mem_openbsd.c
+++ b/src/runtime/mem_openbsd.c
@@ -27,6 +27,29 @@ runtime·sysAlloc(uintptr n, uint64 *stat)
return v;
}
+#pragma textflag NOSPLIT
+void
+runtime·sysMarkStack(void *v, uintptr n)
+{
+ void *p;
+
+ // Stack regions on OpenBSD 6.4+ must be marked with MAP_STACK.
+ p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_FIXED|MAP_STACK, -1, 0);
+ if (p == ((void *)-1) || p != v)
+ runtime·throw("runtime: failed to mark stack");
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·sysUnmarkStack(void *v, uintptr n)
+{
+ void *p;
+
+ p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
+ if (p == ((void *)-1) || p != v)
+ runtime·throw("runtime: failed to unmark stack");
+}
+
void
runtime·SysUnused(void *v, uintptr n)
{
diff --git a/src/runtime/os_openbsd.c b/src/runtime/os_openbsd.c
index eebaa13eea..e5484d993f 100644
--- a/src/runtime/os_openbsd.c
+++ b/src/runtime/os_openbsd.c
@@ -167,7 +167,10 @@ runtime·newosproc(M *mp, void *stk)
param.tf_tcb = (byte*)&mp->tls[0];
param.tf_tid = (int32*)&mp->procid;
- param.tf_stack = stk;
+
+ // Stack pointer must point inside stack area (as marked with MAP_STACK),
+ // rather than at the top of it.
+ param.tf_stack = (void*)((uintptr)stk - sizeof(uintptr));
oset = runtime·sigprocmask(SIG_SETMASK, sigset_all);
ret = runtime·tfork(&param, sizeof(param), mp, mp->g0, runtime·mstart);
diff --git a/src/runtime/stack.c b/src/runtime/stack.c
index cb9557243b..88344d0fc1 100644
--- a/src/runtime/stack.c
+++ b/src/runtime/stack.c
@@ -71,6 +71,9 @@ poolalloc(uint8 order)
runtime·throw("bad ref");
if(s->freelist != nil)
runtime·throw("bad freelist");
+#ifdef GOOS_openbsd
+ runtime·sysMarkStack((void *)(s->start << PageShift), s->npages << PageShift);
+#endif
for(i = 0; i < StackCacheSize; i += FixedStack << order) {
x = (MLink*)((s->start << PageShift) + i);
x->next = s->freelist;
@@ -110,6 +113,9 @@ poolfree(MLink *x, uint8 order)
// span is completely free - return to heap
runtime·MSpanList_Remove(s);
s->freelist = nil;
+#ifdef GOOS_openbsd
+ runtime·sysUnmarkStack((void *)(s->start << PageShift), s->npages << PageShift);
+#endif
runtime·MHeap_FreeStack(&runtime·mheap, s);
}
}
@@ -246,6 +252,9 @@ runtime·stackalloc(uint32 n)
s = runtime·MHeap_AllocStack(&runtime·mheap, ROUND(n, PageSize) >> PageShift);
if(s == nil)
runtime·throw("out of memory");
+#ifdef GOOS_openbsd
+ runtime·sysMarkStack((void *)(s->start << PageShift), s->npages << PageShift);
+#endif
v = (byte*)(s->start<<PageShift);
}
@@ -307,6 +316,9 @@ runtime·stackfree(Stack stk)
runtime·printf("%p %p\n", s->start<<PageShift, v);
runtime·throw("bad span state");
}
+#ifdef GOOS_openbsd
+ runtime·sysUnmarkStack((void *)(s->start << PageShift), s->npages << PageShift);
+#endif
runtime·MHeap_FreeStack(&runtime·mheap, s);
}
}