aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mranges.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2020-07-13 19:51:50 +0000
committerMichael Knyszek <mknyszek@google.com>2020-07-31 14:35:39 +0000
commitb56791cdea5caa87ffcd585d29c294bd3d08a06a (patch)
treeab7f2e6e998e6d89a08bd405d40fd5ac49141d41 /src/runtime/mranges.go
parent10374e2435687a27ac99b2a19284f1aa0c7dc338 (diff)
downloadgo-b56791cdea5caa87ffcd585d29c294bd3d08a06a.tar.xz
runtime: validate candidate searchAddr in pageAlloc.find
Currently pageAlloc.find attempts to find a better estimate for the first free page in the heap, even if the space its looking for isn't necessarily going to be the first free page in the heap (e.g. if npages >= 2). However, in doing so it has the potential to return a searchAddr candidate that doesn't actually correspond to mapped memory, but this candidate might still be adopted. As a result, pageAlloc.alloc's fast path may look at unmapped summary memory and segfault. This case is rare on most operating systems since the heap is kept fairly contiguous, so the chance that the candidate searchAddr discovered is unmapped is fairly low. Even so, this is totally possible and outside the user's control when it happens (in fact, it's likely to happen consistently for a given user on a given system). Fix this problem by ensuring that our candidate always points to mapped memory. We do this by looking at mheap's arenas structure first. If it turns out our candidate doesn't correspond to mapped memory, then we look at inUse to round up the searchAddr to the next mapped address. While we're here, clean up some documentation related to searchAddr. Fixes #40191. Change-Id: I759efec78987e4a8fde466ae45aabbaa3d9d4214 Reviewed-on: https://go-review.googlesource.com/c/go/+/242680 Run-TryBot: Michael Knyszek <mknyszek@google.com> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/mranges.go')
-rw-r--r--src/runtime/mranges.go19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/runtime/mranges.go b/src/runtime/mranges.go
index e23d0778eb..2c0eb2c2dd 100644
--- a/src/runtime/mranges.go
+++ b/src/runtime/mranges.go
@@ -188,6 +188,25 @@ func (a *addrRanges) findSucc(addr uintptr) int {
return len(a.ranges)
}
+// findAddrGreaterEqual returns the smallest address represented by a
+// that is >= addr. Thus, if the address is represented by a,
+// then it returns addr. The second return value indicates whether
+// such an address exists for addr in a. That is, if addr is larger than
+// any address known to a, the second return value will be false.
+func (a *addrRanges) findAddrGreaterEqual(addr uintptr) (uintptr, bool) {
+ i := a.findSucc(addr)
+ if i == 0 {
+ return a.ranges[0].base.addr(), true
+ }
+ if a.ranges[i-1].contains(addr) {
+ return addr, true
+ }
+ if i < len(a.ranges) {
+ return a.ranges[i].base.addr(), true
+ }
+ return 0, false
+}
+
// contains returns true if a covers the address addr.
func (a *addrRanges) contains(addr uintptr) bool {
i := a.findSucc(addr)