aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-12-19 16:16:17 -0500
committerAustin Clements <austin@google.com>2014-12-23 01:33:36 +0000
commit675eb72c285cd0dd44a5f280bb3fa456ddf6de16 (patch)
treeac730d4eaff3ee24c50b5d7c12e010624e0a8a69 /src/runtime
parent3ffc9756d1963e834fbce63ff969de8959216c2b (diff)
downloadgo-675eb72c285cd0dd44a5f280bb3fa456ddf6de16.tar.xz
runtime: run libc SIGSETXID and SIGCANCEL handlers on signal stack
These signals are used by glibc to broadcast setuid/setgid to all threads and to send pthread cancellations. Unlike other signals, the Go runtime does not intercept these because they must invoke the libc handlers (see issues #3871 and #6997). However, because 1) these signals may be issued asynchronously by a thread running C code to another thread running Go code and 2) glibc does not set SA_ONSTACK for its handlers, glibc's signal handler may be run on a Go stack. Signal frames range from 1.5K on amd64 to many kilobytes on ppc64, so this may overflow the Go stack and corrupt heap (or other stack) data. Fix this by ensuring that these signal handlers have the SA_ONSTACK flag (but not otherwise taking over the handler). This has been a problem since Go 1.1, but it's likely that people haven't encountered it because it only affects setuid/setgid and pthread_cancel. Fixes #9600. Change-Id: I6cf5f5c2d3aa48998d632f61f1ddc2778dcfd300 Reviewed-on: https://go-review.googlesource.com/1887 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/os1_darwin.go4
-rw-r--r--src/runtime/os1_dragonfly.go4
-rw-r--r--src/runtime/os1_freebsd.go5
-rw-r--r--src/runtime/os1_linux.go14
-rw-r--r--src/runtime/os1_netbsd.go4
-rw-r--r--src/runtime/os1_openbsd.go4
-rw-r--r--src/runtime/os3_solaris.go4
-rw-r--r--src/runtime/runtime2.go1
-rw-r--r--src/runtime/signal1_unix.go5
-rw-r--r--src/runtime/signal_linux.go4
10 files changed, 47 insertions, 2 deletions
diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go
index 12642aa121..984b88161c 100644
--- a/src/runtime/os1_darwin.go
+++ b/src/runtime/os1_darwin.go
@@ -394,6 +394,10 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(uint32(i), &sa, nil)
}
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
diff --git a/src/runtime/os1_dragonfly.go b/src/runtime/os1_dragonfly.go
index d02e925ec5..0d241bde79 100644
--- a/src/runtime/os1_dragonfly.go
+++ b/src/runtime/os1_dragonfly.go
@@ -189,6 +189,10 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil)
}
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os1_freebsd.go
index 80e4532439..83e98f45e4 100644
--- a/src/runtime/os1_freebsd.go
+++ b/src/runtime/os1_freebsd.go
@@ -190,6 +190,11 @@ func setsig(i int32, fn uintptr, restart bool) {
sa.sa_handler = fn
sigaction(i, &sa, nil)
}
+
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
diff --git a/src/runtime/os1_linux.go b/src/runtime/os1_linux.go
index 2e12d74f44..0174856914 100644
--- a/src/runtime/os1_linux.go
+++ b/src/runtime/os1_linux.go
@@ -246,6 +246,20 @@ func setsig(i int32, fn uintptr, restart bool) {
}
}
+func setsigstack(i int32) {
+ var sa sigactiont
+ if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
+ gothrow("rt_sigaction failure")
+ }
+ if sa.sa_handler == 0 || sa.sa_handler == _SIG_DFL || sa.sa_handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 {
+ return
+ }
+ sa.sa_flags |= _SA_ONSTACK
+ if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
+ gothrow("rt_sigaction failure")
+ }
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go
index b5068629ba..f4de988707 100644
--- a/src/runtime/os1_netbsd.go
+++ b/src/runtime/os1_netbsd.go
@@ -233,6 +233,10 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil)
}
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
index b1a16d582b..07a9751fe0 100644
--- a/src/runtime/os1_openbsd.go
+++ b/src/runtime/os1_openbsd.go
@@ -203,6 +203,10 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil)
}
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index 6ccbbe29ee..72db958f99 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -252,6 +252,10 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil)
}
+func setsigstack(i int32) {
+ gothrow("setsigstack")
+}
+
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 4d42153abb..3b7db1e412 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -372,6 +372,7 @@ const (
_SigHandling = 1 << 5 // our signal handler is registered
_SigIgnored = 1 << 6 // the signal was ignored before we registered for it
_SigGoExit = 1 << 7 // cause all runtime procs to exit (only used on Plan 9).
+ _SigSetStack = 1 << 8 // add SA_ONSTACK to libc handler
)
// Layout of in-memory per-function information prepared by linker
diff --git a/src/runtime/signal1_unix.go b/src/runtime/signal1_unix.go
index 25f01e056e..9613e0ae33 100644
--- a/src/runtime/signal1_unix.go
+++ b/src/runtime/signal1_unix.go
@@ -37,6 +37,11 @@ func initsig() {
}
}
+ if t.flags&_SigSetStack != 0 {
+ setsigstack(i)
+ continue
+ }
+
t.flags |= _SigHandling
setsig(i, funcPC(sighandler), true)
}
diff --git a/src/runtime/signal_linux.go b/src/runtime/signal_linux.go
index 1c3d6872b3..c71e619b1e 100644
--- a/src/runtime/signal_linux.go
+++ b/src/runtime/signal_linux.go
@@ -42,8 +42,8 @@ var sigtable = [...]sigTabT{
/* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
/* 31 */ {_SigNotify, "SIGSYS: bad system call"},
- /* 32 */ {0, "signal 32"}, /* SIGCANCEL; see issue 6997 */
- /* 33 */ {0, "signal 33"}, /* SIGSETXID; see issue 3871 */
+ /* 32 */ {_SigSetStack, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+ /* 33 */ {_SigSetStack, "signal 33"}, /* SIGSETXID; see issue 3871, 9400 */
/* 34 */ {_SigNotify, "signal 34"},
/* 35 */ {_SigNotify, "signal 35"},
/* 36 */ {_SigNotify, "signal 36"},