]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: one more Map{Bits,Spans} before arena_used update
authorAustin Clements <austin@google.com>
Mon, 22 Jun 2015 15:18:23 +0000 (11:18 -0400)
committerAustin Clements <austin@google.com>
Mon, 22 Jun 2015 18:54:38 +0000 (18:54 +0000)
In order to avoid a race with a concurrent write barrier or garbage
collector thread, any update to arena_used must be preceded by mapping
the corresponding heap bitmap and spans array memory. Otherwise, the
concurrent access may observe that a pointer falls within the heap
arena, but then attempt to access unmapped memory to look up its span
or heap bits.

Commit d57c889 fixed all of the places where we updated arena_used
immediately before mapping the heap bitmap and spans, but it missed
the one place where we update arena_used and depend on later code to
update it again and map the bitmap and spans. This creates a window
where the original race can still happen. This commit fixes this by
mapping the heap bitmap and spans before this arena_used update as
well. This code path is only taken when expanding the heap reservation
on 32-bit over a hole in the address space, so these extra mmap calls
should have negligible impact.

Fixes #10212, #11324.

Change-Id: Id67795e6c7563eb551873bc401e5cc997aaa2bd8
Reviewed-on: https://go-review.googlesource.com/11340
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Rick Hudson <rlh@golang.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
src/runtime/malloc.go
src/runtime/mheap.go

index 37d3a1eea18de34a488dd964482896d5a97d91c4..f6608309e8f329fe2f82f46acf2d2f1ce81f7356 100644 (file)
@@ -405,7 +405,10 @@ func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
                                // Keep everything page-aligned.
                                // Our pages are bigger than hardware pages.
                                h.arena_end = p + p_size
-                               h.arena_used = p + (-uintptr(p) & (_PageSize - 1))
+                               used := p + (-uintptr(p) & (_PageSize - 1))
+                               mHeap_MapBits(h, used)
+                               mHeap_MapSpans(h, used)
+                               h.arena_used = used
                                h.arena_reserved = reserved
                        } else {
                                var stat uint64
index fceee7d46434a856fa76dae854e33199575f28db..b73a155700d9a9b5433526cff29bb19b2c4a3e17 100644 (file)
@@ -41,7 +41,7 @@ type mheap struct {
        bitmap         uintptr
        bitmap_mapped  uintptr
        arena_start    uintptr
-       arena_used     uintptr
+       arena_used     uintptr // always mHeap_Map{Bits,Spans} before updating
        arena_end      uintptr
        arena_reserved bool