mirror of
https://github.com/golang/go
synced 2024-11-22 03:24:41 -07:00
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
This commit is contained in:
parent
165bf241f2
commit
aad6b3b32c
@ -18,6 +18,7 @@ package os
|
||||
import (
|
||||
"errors"
|
||||
"internal/syscall/unix"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
@ -151,6 +152,13 @@ var checkPidfdOnce = sync.OnceValue(checkPidfd)
|
||||
// execution environment in which the above system calls are restricted by
|
||||
// seccomp or a similar technology.
|
||||
func checkPidfd() error {
|
||||
// In Android version < 12, pidfd-related system calls are not allowed
|
||||
// by seccomp and trigger the SIGSYS signal. See issue #69065.
|
||||
if runtime.GOOS == "android" {
|
||||
ignoreSIGSYS()
|
||||
defer restoreSIGSYS()
|
||||
}
|
||||
|
||||
// Get a pidfd of the current process (opening of "/proc/self" won't
|
||||
// work for waitid).
|
||||
fd, err := unix.PidFDOpen(syscall.Getpid(), 0)
|
||||
@ -192,3 +200,11 @@ func checkPidfd() error {
|
||||
//
|
||||
//go:linkname checkClonePidfd
|
||||
func checkClonePidfd() error
|
||||
|
||||
// Provided by runtime.
|
||||
//
|
||||
//go:linkname ignoreSIGSYS
|
||||
func ignoreSIGSYS()
|
||||
|
||||
//go:linkname restoreSIGSYS
|
||||
func restoreSIGSYS()
|
||||
|
@ -879,8 +879,9 @@ func runPerThreadSyscall() {
|
||||
}
|
||||
|
||||
const (
|
||||
_SI_USER = 0
|
||||
_SI_TKILL = -6
|
||||
_SI_USER = 0
|
||||
_SI_TKILL = -6
|
||||
_SYS_SECCOMP = 1
|
||||
)
|
||||
|
||||
// sigFromUser reports whether the signal was sent because of a call
|
||||
@ -892,6 +893,14 @@ func (c *sigctxt) sigFromUser() bool {
|
||||
return code == _SI_USER || code == _SI_TKILL
|
||||
}
|
||||
|
||||
// sigFromSeccomp reports whether the signal was sent from seccomp.
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *sigctxt) sigFromSeccomp() bool {
|
||||
code := int32(c.sigcode())
|
||||
return code == _SYS_SECCOMP
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int32) {
|
||||
r, _, err := syscall.Syscall6(syscall.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0)
|
||||
|
@ -13,3 +13,10 @@ package runtime
|
||||
func (c *sigctxt) sigFromUser() bool {
|
||||
return c.sigcode() == _SI_USER
|
||||
}
|
||||
|
||||
// sigFromSeccomp reports whether the signal was sent from seccomp.
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *sigctxt) sigFromSeccomp() bool {
|
||||
return false
|
||||
}
|
||||
|
@ -605,6 +605,19 @@ var crashing atomic.Int32
|
||||
var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
|
||||
var testSigusr1 func(gp *g) bool
|
||||
|
||||
// sigsysIgnored is non-zero if we are currently ignoring SIGSYS. See issue #69065.
|
||||
var sigsysIgnored uint32
|
||||
|
||||
//go:linkname ignoreSIGSYS os.ignoreSIGSYS
|
||||
func ignoreSIGSYS() {
|
||||
atomic.Store(&sigsysIgnored, 1)
|
||||
}
|
||||
|
||||
//go:linkname restoreSIGSYS os.restoreSIGSYS
|
||||
func restoreSIGSYS() {
|
||||
atomic.Store(&sigsysIgnored, 0)
|
||||
}
|
||||
|
||||
// sighandler is invoked when a signal occurs. The global g will be
|
||||
// set to a gsignal goroutine and we will be running on the alternate
|
||||
// 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) {
|
||||
return
|
||||
}
|
||||
|
||||
if sig == _SIGSYS && c.sigFromSeccomp() && atomic.Load(&sigsysIgnored) != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
dieFromSignal(sig)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user