aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mpagealloc.go
diff options
context:
space:
mode:
authorRoland Shoemaker <bracewell@google.com>2025-05-21 02:03:44 +0000
committerRoland Shoemaker <roland@golang.org>2025-07-24 09:59:23 -0700
commit6669aa3b14d98d90929ca860421e5308374b0f46 (patch)
tree52f29bd6ddecd9e4b8aef63416d2d8f819cbad3c /src/runtime/mpagealloc.go
parent26338a7f691b45017168b6523c95d4578a2cfd4d (diff)
downloadgo-6669aa3b14d98d90929ca860421e5308374b0f46.tar.xz
runtime: randomize heap base address
During initialization, allow randomizing the heap base address by generating a random uint64 and using its bits to randomize various portions of the heap base address. We use the following method to randomize the base address: * We first generate a random heapArenaBytes aligned address that we use for generating the hints. * On the first call to mheap.grow, we then generate a random PallocChunkBytes aligned offset into the mmap'd heap region, which we use as the base for the heap region. * We then mark a random number of pages within the page allocator as allocated. Our final randomized "heap base address" becomes the first byte of the first available page returned by the page allocator. This results in an address with at least heapAddrBits-gc.PageShift-1 bits of entropy. Fixes #27583 Change-Id: Ideb4450a5ff747a132f702d563d2a516dec91a88 Reviewed-on: https://go-review.googlesource.com/c/go/+/674835 Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/runtime/mpagealloc.go')
-rw-r--r--src/runtime/mpagealloc.go39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go
index 4c58fb6e02..83db005051 100644
--- a/src/runtime/mpagealloc.go
+++ b/src/runtime/mpagealloc.go
@@ -972,6 +972,45 @@ func (p *pageAlloc) free(base, npages uintptr) {
p.update(base, npages, true, false)
}
+// markRandomPaddingPages marks the range of memory [base, base+npages*pageSize]
+// as both allocated and scavenged. This is used for randomizing the base heap
+// address. Both the alloc and scav bits are set so that the pages are not used
+// and so the memory accounting stats are correctly calculated.
+//
+// Similar to allocRange, it also updates the summaries to reflect the
+// newly-updated bitmap.
+//
+// p.mheapLock must be held.
+func (p *pageAlloc) markRandomPaddingPages(base uintptr, npages uintptr) {
+ assertLockHeld(p.mheapLock)
+
+ limit := base + npages*pageSize - 1
+ sc, ec := chunkIndex(base), chunkIndex(limit)
+ si, ei := chunkPageIndex(base), chunkPageIndex(limit)
+ if sc == ec {
+ chunk := p.chunkOf(sc)
+ chunk.allocRange(si, ei+1-si)
+ p.scav.index.alloc(sc, ei+1-si)
+ chunk.scavenged.setRange(si, ei+1-si)
+ } else {
+ chunk := p.chunkOf(sc)
+ chunk.allocRange(si, pallocChunkPages-si)
+ p.scav.index.alloc(sc, pallocChunkPages-si)
+ chunk.scavenged.setRange(si, pallocChunkPages-si)
+ for c := sc + 1; c < ec; c++ {
+ chunk := p.chunkOf(c)
+ chunk.allocAll()
+ p.scav.index.alloc(c, pallocChunkPages)
+ chunk.scavenged.setAll()
+ }
+ chunk = p.chunkOf(ec)
+ chunk.allocRange(0, ei+1)
+ p.scav.index.alloc(ec, ei+1)
+ chunk.scavenged.setRange(0, ei+1)
+ }
+ p.update(base, npages, true, true)
+}
+
const (
pallocSumBytes = unsafe.Sizeof(pallocSum(0))