]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.23] 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>
Wed, 2 Oct 2024 16:52:24 +0000 (16:52 +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.

For #69065
Fixes #69640

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>
(cherry picked from commit a3a05ed04cb53c53bdacded2d16f0f3e5facdbb0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/616077
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>

src/os/pidfd_linux.go
src/runtime/os_linux.go
src/runtime/os_unix_nonlinux.go
src/runtime/signal_unix.go

index 545cfe9613b8b4e5710c16efc863a8d2d6c72953..01a98ca17c286f34d62db00101d453e2326a1c20 100644 (file)
@@ -14,6 +14,7 @@ package os
 import (
        "errors"
        "internal/syscall/unix"
+       "runtime"
        "sync"
        "syscall"
        "unsafe"
@@ -147,6 +148,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)
@@ -174,3 +182,11 @@ func checkPidfd() error {
 
        return nil
 }
+
+// Provided by runtime.
+//
+//go:linkname ignoreSIGSYS
+func ignoreSIGSYS()
+
+//go:linkname restoreSIGSYS
+func restoreSIGSYS()
index 6ce656c70e146e57f870e3227dc7c7a1862d31f2..e80d390e0d09f26b65ef79cfa1426a47373a6f05 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 8ba498bdb238d5d9f9293d8ac83563934af775d2..6f40f440e807f8bd5d05a501d39e71ae15737508 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)
        }