runtime: add test for systemstack frame pointer adjustment

Add TestSystemstackFramePointerAdjust as a regression test for CL
489015.

By turning stackPoisonCopy into a var instead of const and introducing
the ShrinkStackAndVerifyFramePointers() helper function, we are able to
trigger the exact combination of events that can crash traceEvent() if
systemstack restores a frame pointer that is pointing into the old
stack.

Updates #59692

Change-Id: I60fc6940638077e3b60a81d923b5f5b4f6d8a44c
Reviewed-on: https://go-review.googlesource.com/c/go/+/489115
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Felix Geisendörfer <felix.geisendoerfer@datadoghq.com>
This commit is contained in:
Felix Geisendörfer 2023-04-26 10:07:02 +02:00 committed by Cherry Mui
parent 0d347544cb
commit 6dca1a29ab
3 changed files with 40 additions and 1 deletions

View file

@ -423,6 +423,23 @@ func ReadMemStatsSlow() (base, slow MemStats) {
return
}
// ShrinkStackAndVerifyFramePointers attempts to shrink the stack of the current goroutine
// and verifies that unwinding the new stack doesn't crash, even if the old
// stack has been freed or reused (simulated via poisoning).
func ShrinkStackAndVerifyFramePointers() {
before := stackPoisonCopy
defer func() { stackPoisonCopy = before }()
stackPoisonCopy = 1
gp := getg()
systemstack(func() {
shrinkstack(gp)
})
// If our new stack contains frame pointers into the old stack, this will
// crash because the old stack has been poisoned.
FPCallers(0, make([]uintptr, 1024))
}
// BlockOnSystemStack switches to the system stack, prints "x\n" to
// stderr, and blocks in a stack containing
// "runtime.blockOnSystemStackInternal".