syscall: add //go:norace to rawSyscall on darwin On darwin, rawSyscall, rawSyscall6, and rawSyscall9 are Go functions (not assembly as on Linux) that get race-detector instrumentation. When forkAndExecInChild calls rawSyscall in the forked child process, the TSan ThreadState pointer is invalid, causing SIGSEGV in TraceSwitchPartImpl. Add //go:norace to these functions so the race detector does not instrument them. Also update the stale comment in exec_libc2.go that referred to rawSyscall as assembly. Fixes #79804 Change-Id: Ia1d5ffea9bc9729ce5392daaf00b45ab1f779d71 GitHub-Last-Rev: 21d574438c6ff11cd4939d463955152315827680 GitHub-Pull-Request: golang/go#79805 Reviewed-on: https://go-review.googlesource.com/c/go/+/786620 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Quim Muntal <quimmuntal@gmail.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/src/syscall/exec_libc2.go b/src/syscall/exec_libc2.go index 3de2c94..50f8d42 100644 --- a/src/syscall/exec_libc2.go +++ b/src/syscall/exec_libc2.go
@@ -48,8 +48,9 @@ // they might have been locked at the time of the fork. This means // no rescheduling, no malloc calls, and no new stack segments. // For the same reason compiler does not race instrument it. -// The calls to rawSyscall are okay because they are assembly -// functions that do not grow the stack. +// The calls to rawSyscall are okay because they are nosplit +// functions that do not grow the stack and are not race +// instrumented (go:norace). // //go:norace func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err1 Errno) {
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go index ca76cc2..b65f69f 100644 --- a/src/syscall/syscall_darwin.go +++ b/src/syscall/syscall_darwin.go
@@ -326,6 +326,7 @@ // errno return e if int32(r) is -1, else it returns 0. // //go:nosplit +//go:norace func errno(r uintptr, e Errno) Errno { if int32(r) == -1 { return e @@ -336,6 +337,7 @@ // errnoX return e if r is -1, else it returns 0. // //go:nosplit +//go:norace func errnoX(r uintptr, e Errno) Errno { if r == ^uintptr(0) { return e @@ -346,6 +348,7 @@ // errnoPtr return e if r is 0, else it returns 0. // //go:nosplit +//go:norace func errnoPtr(r uintptr, e Errno) Errno { if r == 0 { return e @@ -358,6 +361,22 @@ // golang.org/x/sys linknames the following syscalls. // Do not remove or change the type signature. +// N.B. For the Syscall functions below: +// +// //go:uintptrkeepalive because the uintptr argument may be converted pointers +// that need to be kept alive in the caller. +// +// //go:nosplit because stack copying does not account for uintptrkeepalive, so +// the stack must not grow. Stack copying cannot blindly assume that all +// uintptr arguments are pointers, because some values may look like pointers, +// but not really be pointers, and adjusting their value would break the call. +// +// //go:norace, on RawSyscall, to avoid race instrumentation if RawSyscall is +// called after fork, or from a signal handler. +// +// //go:linkname to ensure ABI wrappers are generated for external callers +// (notably x/sys/unix assembly). + //go:linkname syscall //go:nosplit //go:uintptrkeepalive @@ -409,6 +428,7 @@ //go:linkname rawSyscall //go:nosplit +//go:norace //go:uintptrkeepalive func rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { r1, r2, err = rawsyscalln(fn, a1, a2, a3) @@ -417,6 +437,7 @@ //go:linkname rawSyscall6 //go:nosplit +//go:norace //go:uintptrkeepalive func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { r1, r2, err = rawsyscalln(fn, a1, a2, a3, a4, a5, a6) @@ -425,6 +446,7 @@ //go:linkname rawSyscall9 //go:nosplit +//go:norace //go:uintptrkeepalive func rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) { r1, r2, err = rawsyscalln(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)