Skip to content

Commit aad6b3b

Browse files
committed
os: ignore SIGSYS in checkPidfd
In Android version 11 and earlier, pidfd-related system calls are not allowed by the seccomp policy, which causes crashes due to SIGSYS signals. Fixes #69065
1 parent 165bf24 commit aad6b3b

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

src/os/pidfd_linux.go

+16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package os
1818
import (
1919
"errors"
2020
"internal/syscall/unix"
21+
"runtime"
2122
"sync"
2223
"syscall"
2324
"unsafe"
@@ -151,6 +152,13 @@ var checkPidfdOnce = sync.OnceValue(checkPidfd)
151152
// execution environment in which the above system calls are restricted by
152153
// seccomp or a similar technology.
153154
func checkPidfd() error {
155+
// In Android version < 12, pidfd-related system calls are not allowed
156+
// by seccomp and trigger the SIGSYS signal. See issue #69065.
157+
if runtime.GOOS == "android" {
158+
ignoreSIGSYS()
159+
defer restoreSIGSYS()
160+
}
161+
154162
// Get a pidfd of the current process (opening of "/proc/self" won't
155163
// work for waitid).
156164
fd, err := unix.PidFDOpen(syscall.Getpid(), 0)
@@ -192,3 +200,11 @@ func checkPidfd() error {
192200
//
193201
//go:linkname checkClonePidfd
194202
func checkClonePidfd() error
203+
204+
// Provided by runtime.
205+
//
206+
//go:linkname ignoreSIGSYS
207+
func ignoreSIGSYS()
208+
209+
//go:linkname restoreSIGSYS
210+
func restoreSIGSYS()

src/runtime/os_linux.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -879,8 +879,9 @@ func runPerThreadSyscall() {
879879
}
880880

881881
const (
882-
_SI_USER = 0
883-
_SI_TKILL = -6
882+
_SI_USER = 0
883+
_SI_TKILL = -6
884+
_SYS_SECCOMP = 1
884885
)
885886

886887
// sigFromUser reports whether the signal was sent because of a call
@@ -892,6 +893,14 @@ func (c *sigctxt) sigFromUser() bool {
892893
return code == _SI_USER || code == _SI_TKILL
893894
}
894895

896+
// sigFromSeccomp reports whether the signal was sent from seccomp.
897+
//
898+
//go:nosplit
899+
func (c *sigctxt) sigFromSeccomp() bool {
900+
code := int32(c.sigcode())
901+
return code == _SYS_SECCOMP
902+
}
903+
895904
//go:nosplit
896905
func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int32) {
897906
r, _, err := syscall.Syscall6(syscall.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0)

src/runtime/os_unix_nonlinux.go

+7
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@ package runtime
1313
func (c *sigctxt) sigFromUser() bool {
1414
return c.sigcode() == _SI_USER
1515
}
16+
17+
// sigFromSeccomp reports whether the signal was sent from seccomp.
18+
//
19+
//go:nosplit
20+
func (c *sigctxt) sigFromSeccomp() bool {
21+
return false
22+
}

src/runtime/signal_unix.go

+17
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,19 @@ var crashing atomic.Int32
605605
var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
606606
var testSigusr1 func(gp *g) bool
607607

608+
// sigsysIgnored is non-zero if we are currently ignoring SIGSYS. See issue #69065.
609+
var sigsysIgnored uint32
610+
611+
//go:linkname ignoreSIGSYS os.ignoreSIGSYS
612+
func ignoreSIGSYS() {
613+
atomic.Store(&sigsysIgnored, 1)
614+
}
615+
616+
//go:linkname restoreSIGSYS os.restoreSIGSYS
617+
func restoreSIGSYS() {
618+
atomic.Store(&sigsysIgnored, 0)
619+
}
620+
608621
// sighandler is invoked when a signal occurs. The global g will be
609622
// set to a gsignal goroutine and we will be running on the alternate
610623
// signal stack. The parameter gp will be the value of the global g
@@ -715,6 +728,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
715728
return
716729
}
717730

731+
if sig == _SIGSYS && c.sigFromSeccomp() && atomic.Load(&sigsysIgnored) != 0 {
732+
return
733+
}
734+
718735
if flags&_SigKill != 0 {
719736
dieFromSignal(sig)
720737
}

0 commit comments

Comments
 (0)