From 3a273a9919687493bc9912177a969a8f4617ceb4 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 5 Sep 2019 06:22:23 +0100 Subject: [PATCH] fixes #32912 The crash occurs when go runtime calls a VDSO function (say __vdso_clock_gettime) and a signal arrives to that thread. Since VDSO functions temporarily destroy the G register (R10), Go functions asynchronously executed in that thread (i.e. Go's signal handler) can try to load data from the destroyed G, which causes segmentation fault. --- src/runtime/signal_unix.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 436c18c1261f54..d3e44fdd0f583a 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -289,7 +289,10 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { if sigfwdgo(sig, info, ctx) { return } - g := getg() + var g *g = nil + if !inVDSOPage(uintptr(info.si_addr)) { + g = getg() + } if g == nil { c := &sigctxt{info, ctx} if sig == _SIGPROF { @@ -657,8 +660,12 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { return false } // Determine if the signal occurred inside Go code. We test that: - // (1) we were in a goroutine (i.e., m.curg != nil), and - // (2) we weren't in CGO. + // (1) we weren't in VDSO page, + // (2) we were in a goroutine (i.e., m.curg != nil), and + // (3) we weren't in CGO. + if inVDSOPage(uintptr(info.si_addr)) { + return false + } g := getg() if g != nil && g.m != nil && g.m.curg != nil && !g.m.incgo { return false