Skip to content

Commit f8e6418

Browse files
committed
runtime: fix bad signal stack when using cgo-created threads and async signals
Cgo-created threads transition between having associated Go g's and m's and not. A signal arriving during the transition could think it was safe and appropriate to run Go signal handlers when it was in fact not. Avoid the race by masking all signals during the transition. Fixes #12277. Change-Id: Ie9711bc1d098391d58362492197a7e0f5b497d14 Reviewed-on: https://go-review.googlesource.com/16915 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 921e7df commit f8e6418

11 files changed

+140
-27
lines changed

src/runtime/os1_darwin.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ func mpreinit(mp *m) {
130130
mp.gsignal.m = mp
131131
}
132132

133+
//go:nosplit
133134
func msigsave(mp *m) {
134135
smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
135136
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -138,6 +139,17 @@ func msigsave(mp *m) {
138139
sigprocmask(_SIG_SETMASK, nil, smask)
139140
}
140141

142+
//go:nosplit
143+
func msigrestore(mp *m) {
144+
smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
145+
sigprocmask(_SIG_SETMASK, smask, nil)
146+
}
147+
148+
//go:nosplit
149+
func sigblock() {
150+
sigprocmask(_SIG_SETMASK, &sigset_all, nil)
151+
}
152+
141153
// Called to initialize a new m (including the bootstrap m).
142154
// Called on the new thread, can not allocate memory.
143155
func minit() {
@@ -156,10 +168,8 @@ func minit() {
156168
}
157169

158170
// Called from dropm to undo the effect of an minit.
171+
//go:nosplit
159172
func unminit() {
160-
_g_ := getg()
161-
smask := (*uint32)(unsafe.Pointer(&_g_.m.sigmask))
162-
sigprocmask(_SIG_SETMASK, smask, nil)
163173
signalstack(nil)
164174
}
165175

@@ -459,6 +469,7 @@ func getsig(i int32) uintptr {
459469
return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
460470
}
461471

472+
//go:nosplit
462473
func signalstack(s *stack) {
463474
var st stackt
464475
if s == nil {

src/runtime/os1_dragonfly.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func mpreinit(mp *m) {
117117
mp.gsignal.m = mp
118118
}
119119

120+
//go:nosplit
120121
func msigsave(mp *m) {
121122
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
122123
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -125,6 +126,17 @@ func msigsave(mp *m) {
125126
sigprocmask(_SIG_SETMASK, nil, smask)
126127
}
127128

129+
//go:nosplit
130+
func msigrestore(mp *m) {
131+
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
132+
sigprocmask(_SIG_SETMASK, smask, nil)
133+
}
134+
135+
//go:nosplit
136+
func sigblock() {
137+
sigprocmask(_SIG_SETMASK, &sigset_all, nil)
138+
}
139+
128140
// Called to initialize a new m (including the bootstrap m).
129141
// Called on the new thread, can not allocate memory.
130142
func minit() {
@@ -148,9 +160,6 @@ func minit() {
148160

149161
// Called from dropm to undo the effect of an minit.
150162
func unminit() {
151-
_g_ := getg()
152-
smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
153-
sigprocmask(_SIG_SETMASK, smask, nil)
154163
signalstack(nil)
155164
}
156165

@@ -220,6 +229,7 @@ func getsig(i int32) uintptr {
220229
return sa.sa_sigaction
221230
}
222231

232+
//go:nosplit
223233
func signalstack(s *stack) {
224234
var st sigaltstackt
225235
if s == nil {

src/runtime/os1_freebsd.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func mpreinit(mp *m) {
120120
mp.gsignal.m = mp
121121
}
122122

123+
//go:nosplit
123124
func msigsave(mp *m) {
124125
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
125126
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -128,6 +129,17 @@ func msigsave(mp *m) {
128129
sigprocmask(_SIG_SETMASK, nil, smask)
129130
}
130131

132+
//go:nosplit
133+
func msigrestore(mp *m) {
134+
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
135+
sigprocmask(_SIG_SETMASK, smask, nil)
136+
}
137+
138+
//go:nosplit
139+
func sigblock() {
140+
sigprocmask(_SIG_SETMASK, &sigset_all, nil)
141+
}
142+
131143
// Called to initialize a new m (including the bootstrap m).
132144
// Called on the new thread, can not allocate memory.
133145
func minit() {
@@ -153,10 +165,8 @@ func minit() {
153165
}
154166

155167
// Called from dropm to undo the effect of an minit.
168+
//go:nosplit
156169
func unminit() {
157-
_g_ := getg()
158-
smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
159-
sigprocmask(_SIG_SETMASK, smask, nil)
160170
signalstack(nil)
161171
}
162172

@@ -226,6 +236,7 @@ func getsig(i int32) uintptr {
226236
return sa.sa_handler
227237
}
228238

239+
//go:nosplit
229240
func signalstack(s *stack) {
230241
var st stackt
231242
if s == nil {

src/runtime/os1_linux.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ func mpreinit(mp *m) {
197197
mp.gsignal.m = mp
198198
}
199199

200+
//go:nosplit
200201
func msigsave(mp *m) {
201202
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
202203
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -205,6 +206,17 @@ func msigsave(mp *m) {
205206
rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask)))
206207
}
207208

209+
//go:nosplit
210+
func msigrestore(mp *m) {
211+
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
212+
rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
213+
}
214+
215+
//go:nosplit
216+
func sigblock() {
217+
rtsigprocmask(_SIG_SETMASK, &sigset_all, nil, int32(unsafe.Sizeof(sigset_all)))
218+
}
219+
208220
func gettid() uint32
209221

210222
// Called to initialize a new m (including the bootstrap m).
@@ -228,10 +240,8 @@ func minit() {
228240
}
229241

230242
// Called from dropm to undo the effect of an minit.
243+
//go:nosplit
231244
func unminit() {
232-
_g_ := getg()
233-
smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
234-
rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
235245
signalstack(nil)
236246
}
237247

@@ -325,6 +335,7 @@ func getsig(i int32) uintptr {
325335
return sa.sa_handler
326336
}
327337

338+
//go:nosplit
328339
func signalstack(s *stack) {
329340
var st sigaltstackt
330341
if s == nil {

src/runtime/os1_nacl.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@ func mpreinit(mp *m) {
1515

1616
func sigtramp()
1717

18+
//go:nosplit
1819
func msigsave(mp *m) {
1920
}
2021

22+
//go:nosplit
23+
func msigrestore(mp *m) {
24+
}
25+
26+
//go:nosplit
27+
func sigblock() {
28+
}
29+
2130
// Called to initialize a new m (including the bootstrap m).
2231
// Called on the new thread, can not allocate memory.
2332
func minit() {

src/runtime/os1_netbsd.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ func mpreinit(mp *m) {
138138
mp.gsignal.m = mp
139139
}
140140

141+
//go:nosplit
141142
func msigsave(mp *m) {
142143
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
143144
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -146,6 +147,17 @@ func msigsave(mp *m) {
146147
sigprocmask(_SIG_SETMASK, nil, smask)
147148
}
148149

150+
//go:nosplit
151+
func msigrestore(mp *m) {
152+
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
153+
sigprocmask(_SIG_SETMASK, smask, nil)
154+
}
155+
156+
//go:nosplit
157+
func sigblock() {
158+
sigprocmask(_SIG_SETMASK, &sigset_all, nil)
159+
}
160+
149161
// Called to initialize a new m (including the bootstrap m).
150162
// Called on the new thread, can not allocate memory.
151163
func minit() {
@@ -166,11 +178,8 @@ func minit() {
166178
}
167179

168180
// Called from dropm to undo the effect of an minit.
181+
//go:nosplit
169182
func unminit() {
170-
_g_ := getg()
171-
smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
172-
sigprocmask(_SIG_SETMASK, smask, nil)
173-
174183
signalstack(nil)
175184
}
176185

@@ -213,6 +222,7 @@ func getsig(i int32) uintptr {
213222
return sa.sa_sigaction
214223
}
215224

225+
//go:nosplit
216226
func signalstack(s *stack) {
217227
var st sigaltstackt
218228
if s == nil {

src/runtime/os1_openbsd.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ func mpreinit(mp *m) {
148148
mp.gsignal.m = mp
149149
}
150150

151+
//go:nosplit
151152
func msigsave(mp *m) {
152153
smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
153154
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -156,6 +157,17 @@ func msigsave(mp *m) {
156157
*smask = sigprocmask(_SIG_BLOCK, 0)
157158
}
158159

160+
//go:nosplit
161+
func msigrestore(mp *m) {
162+
smask := *(*uint32)(unsafe.Pointer(&mp.sigmask))
163+
sigprocmask(_SIG_SETMASK, smask)
164+
}
165+
166+
//go:nosplit
167+
func sigblock() {
168+
sigprocmask(_SIG_SETMASK, sigset_all)
169+
}
170+
159171
// Called to initialize a new m (including the bootstrap m).
160172
// Called on the new thread, can not allocate memory.
161173
func minit() {
@@ -178,10 +190,8 @@ func minit() {
178190
}
179191

180192
// Called from dropm to undo the effect of an minit.
193+
//go:nosplit
181194
func unminit() {
182-
_g_ := getg()
183-
smask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
184-
sigprocmask(_SIG_SETMASK, smask)
185195
signalstack(nil)
186196
}
187197

@@ -224,6 +234,7 @@ func getsig(i int32) uintptr {
224234
return sa.sa_sigaction
225235
}
226236

237+
//go:nosplit
227238
func signalstack(s *stack) {
228239
var st stackt
229240
if s == nil {

src/runtime/os1_plan9.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ func mpreinit(mp *m) {
2424
func msigsave(mp *m) {
2525
}
2626

27+
func msigrestore(mp *m) {
28+
}
29+
30+
func sigblock() {
31+
}
32+
2733
// Called to initialize a new m (including the bootstrap m).
2834
// Called on the new thread, can not allocate memory.
2935
func minit() {

src/runtime/os1_windows.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,18 @@ func newosproc(mp *m, stk unsafe.Pointer) {
390390
func mpreinit(mp *m) {
391391
}
392392

393+
//go:nosplit
393394
func msigsave(mp *m) {
394395
}
395396

397+
//go:nosplit
398+
func msigrestore(mp *m) {
399+
}
400+
401+
//go:nosplit
402+
func sigblock() {
403+
}
404+
396405
// Called to initialize a new m (including the bootstrap m).
397406
// Called on the new thread, can not allocate memory.
398407
func minit() {
@@ -402,6 +411,7 @@ func minit() {
402411
}
403412

404413
// Called from dropm to undo the effect of an minit.
414+
//go:nosplit
405415
func unminit() {
406416
tp := &getg().m.thread
407417
stdcall1(_CloseHandle, *tp)

src/runtime/os3_solaris.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ func mpreinit(mp *m) {
192192

193193
func miniterrno()
194194

195+
//go:nosplit
195196
func msigsave(mp *m) {
196197
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
197198
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -200,6 +201,17 @@ func msigsave(mp *m) {
200201
sigprocmask(_SIG_SETMASK, nil, smask)
201202
}
202203

204+
//go:nosplit
205+
func msigrestore(mp *m) {
206+
smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
207+
sigprocmask(_SIG_SETMASK, smask, nil)
208+
}
209+
210+
//go:nosplit
211+
func sigblock() {
212+
sigprocmask(_SIG_SETMASK, &sigset_all, nil)
213+
}
214+
203215
// Called to initialize a new m (including the bootstrap m).
204216
// Called on the new thread, can not allocate memory.
205217
func minit() {
@@ -220,10 +232,6 @@ func minit() {
220232

221233
// Called from dropm to undo the effect of an minit.
222234
func unminit() {
223-
_g_ := getg()
224-
smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
225-
sigprocmask(_SIG_SETMASK, smask, nil)
226-
227235
signalstack(nil)
228236
}
229237

@@ -289,6 +297,7 @@ func getsig(i int32) uintptr {
289297
return *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
290298
}
291299

300+
//go:nosplit
292301
func signalstack(s *stack) {
293302
var st sigaltstackt
294303
if s == nil {
@@ -497,6 +506,7 @@ func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
497506
sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
498507
}
499508

509+
//go:nosplit
500510
func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
501511
sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
502512
}

0 commit comments

Comments
 (0)