Skip to content

Commit 4b53547

Browse files
committed
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.
1 parent 5d04e76 commit 4b53547

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

src/runtime/signal_unix.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,12 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
289289
if sigfwdgo(sig, info, ctx) {
290290
return
291291
}
292-
g := getg()
292+
c := &sigctxt{info, ctx}
293+
var g *g
294+
if !inVDSOPage(c.sigpc()) {
295+
g = getg()
296+
}
293297
if g == nil {
294-
c := &sigctxt{info, ctx}
295298
if sig == _SIGPROF {
296299
sigprofNonGoPC(c.sigpc())
297300
return
@@ -347,7 +350,6 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
347350
signalDuringFork(sig)
348351
}
349352

350-
c := &sigctxt{info, ctx}
351353
c.fixsigcode(sig)
352354
sighandler(sig, info, ctx, g)
353355
setg(g)
@@ -657,8 +659,12 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
657659
return false
658660
}
659661
// Determine if the signal occurred inside Go code. We test that:
660-
// (1) we were in a goroutine (i.e., m.curg != nil), and
661-
// (2) we weren't in CGO.
662+
// (1) we weren't in VDSO page,
663+
// (2) we were in a goroutine (i.e., m.curg != nil), and
664+
// (3) we weren't in CGO.
665+
if inVDSOPage(c.sigpc()) {
666+
return false
667+
}
662668
g := getg()
663669
if g != nil && g.m != nil && g.m.curg != nil && !g.m.incgo {
664670
return false

src/runtime/vdso_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ func vdsoauxv(tag, val uintptr) {
281281
}
282282

283283
// vdsoMarker reports whether PC is on the VDSO page.
284+
//go:nosplit
284285
func inVDSOPage(pc uintptr) bool {
285286
for _, k := range vdsoSymbolKeys {
286287
if *k.ptr != 0 {

0 commit comments

Comments
 (0)