aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2023-12-08 13:50:22 -0800
committerKeith Randall <khr@golang.org>2023-12-11 17:15:22 +0000
commit052d402985816c1fc0f07424e53eaace3fa5e408 (patch)
treee7afcfbd6ad0917d9ce6e3968272262fd4d98455
parent59275e266a222564fc1a39f17b913a74838478f4 (diff)
downloadgo-052d402985816c1fc0f07424e53eaace3fa5e408.tar.xz
runtime: clear mspan.largeType more carefully in the case of arenas
The pointer stored in mspan.largeType is an invalid pointer when the span is an arena. We need to make sure that pointer isn't seen by the garbage collector, as it might barf on it. Make sure we zero the pointer using a uintptr write so the old value isn't picked up by the write barrier. The mspan.largeType field itself is in a NotInHeap struct, so a heap scan won't find it. The only way we find it is when writing it, or when reading it and putting it in a GC-reachable location. I think we might need to audit the runtime to make sure these pointers aren't being passed in places where the GC might (non-conservatively) scan a stack frame it lives in. (It might be ok, many such places are either systemstack or nosplit.) Change-Id: Ie059d054e0da4d48a4c4b3be88b8e1e46ffa7d10 Reviewed-on: https://go-review.googlesource.com/c/go/+/548535 Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
-rw-r--r--src/runtime/mgcsweep.go5
1 files changed, 4 insertions, 1 deletions
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go
index 2d84c0d07c..0fbb23d573 100644
--- a/src/runtime/mgcsweep.go
+++ b/src/runtime/mgcsweep.go
@@ -796,7 +796,10 @@ func (sl *sweepLocked) sweep(preserve bool) bool {
s := spanOf(uintptr(unsafe.Pointer(s.largeType)))
mheap_.freeManual(s, spanAllocPtrScalarBits)
})
- s.largeType = nil
+ // Make sure to zero this pointer without putting the old
+ // value in a write buffer, as the old value might be an
+ // invalid pointer. See arena.go:(*mheap).allocUserArenaChunk.
+ *(*uintptr)(unsafe.Pointer(&s.largeType)) = 0
}
// Count the free in the consistent, external stats.