aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/signal_unix.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-11-30 22:09:35 -0500
committerAustin Clements <austin@google.com>2017-12-01 20:20:45 +0000
commit292558be025fb0a959f7d594771c2833149521db (patch)
tree1ff875e7228de598318b00825b4d1c05347c3627 /src/runtime/signal_unix.go
parent1c55f579be28c2e959bdfbe7688cba06556dff4b (diff)
downloadgo-292558be025fb0a959f7d594771c2833149521db.tar.gz
go-292558be025fb0a959f7d594771c2833149521db.zip
runtime: restore the Go-allocated signal stack in unminit
Currently, when we minit on a thread that already has an alternate signal stack (e.g., because the M was an extram being used for a cgo callback, or to handle a signal on a C thread, or because the platform's libc always allocates a signal stack like on Android), we simply drop the Go-allocated gsignal stack on the floor. This is a problem for Ms on the extram list because those Ms may later be reused for a different thread that may not have its own alternate signal stack. On tip, this manifests as a crash in sigaltstack because we clear the gsignal stack bounds in unminit and later try to use those cleared bounds when we re-minit that M. On 1.9 and earlier, we didn't clear the bounds, so this manifests as running more than one signal handler on the same signal stack, which could lead to arbitrary memory corruption. This CL fixes this problem by saving the Go-allocated gsignal stack in a new field in the m struct when overwriting it with a system-provided signal stack, and then restoring the original gsignal stack in unminit. This CL is designed to be easy to back-port to 1.9. It won't quite cherry-pick cleanly, but it should be sufficient to simply ignore the change in mexit (which didn't exist in 1.9). Now that we always have a place to stash the original signal stack in the m struct, there are some simplifications we can make to the signal stack handling. We'll do those in a later CL. Fixes #22930. Change-Id: I55c5a6dd9d97532f131146afdef0b216e1433054 Reviewed-on: https://go-review.googlesource.com/81476 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r--src/runtime/signal_unix.go12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index e1ba2dbc78..2cd3d71800 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -720,7 +720,7 @@ func minitSignalStack() {
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
} else {
- setGsignalStack(&st, nil)
+ setGsignalStack(&st, &_g_.m.goSigStack)
_g_.m.newSigstack = false
}
}
@@ -751,9 +751,13 @@ func unminitSignals() {
st := stackt{ss_flags: _SS_DISABLE}
sigaltstack(&st, nil)
} else {
- // We got the signal stack from someone else. Clear it
- // so we don't get confused.
- getg().m.gsignal.stack = stack{}
+ // We got the signal stack from someone else. Restore
+ // the Go-allocated stack in case this M gets reused
+ // for another thread (e.g., it's an extram). Also, on
+ // Android, libc allocates a signal stack for all
+ // threads, so it's important to restore the Go stack
+ // even on Go-created threads so we can free it.
+ restoreGsignalStack(&getg().m.goSigStack)
}
}