]> Cypherpunks repositories - gostls13.git/commitdiff
os: ignore SIGSYS in checkPidfd
authorcions <gh.cions@gmail.com>
Tue, 24 Sep 2024 01:27:40 +0000 (01:27 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 26 Sep 2024 13:17:09 +0000 (13:17 +0000)
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

Change-Id: Ib29631639a5cf221ac11b4d82390cb79436b8657
GitHub-Last-Rev: aad6b3b32c81795f86bc4a9e81aad94899daf520
GitHub-Pull-Request: golang/go#69543
Reviewed-on: https://go-review.googlesource.com/c/go/+/614277
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/os/pidfd_linux.go
src/runtime/os_linux.go
src/runtime/os_unix_nonlinux.go
src/runtime/signal_unix.go

index 459d88cb445b427dc8197778759c7df4fe40b409..0bfef7759cc67970ed97137dd43beb7ab60bd0da 100644 (file)
@@ -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()
index 3911276cf2c7f47f6fdef0cc6a65ed67844b7386..e18ef8e77623619c88fe90e7b4091ea8ddcc6f1a 100644 (file)
@@ -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)
index b98753b8fe12b70027e3017c934ff754febaa8c6..0e8b61c3b11aa2d34ae4e7e122115906a583e57d 100644 (file)
@@ -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
+}
index a6373093b5f531bfd9e45196f10dfc6fea568175..a056e21a2f9cee90a993bb518cd025634de6a9bc 100644 (file)
@@ -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)
        }