syscall: use rawSyscall6 to call ptrace in forkAndExecInChild

On darwin and openbsd, the autogenerated ptrace wrapper is
nosplit because it is called from forkAndExecInChild.

This makes it difficult to modify and improve the underlying
syscall mechanism, as ptrace is almost over the nosplit limit.

We better call ptrace directly using rawSyscall6 in
forkAndExecInChild so that we can lift the ptrace nosplit
restriction to.

Doing so also fixes a long-standing inconsistency:
forkAndExecInChild is documented to only allow rawSyscall, but
the ptrace wrapper is using non-raw syscalls.

Updates #64113

Change-Id: Ibbbb218511561c1a5cb5b6d288a691f9738b14a6
Reviewed-on: https://go-review.googlesource.com/c/go/+/708575
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
qmuntal 2025-10-02 15:12:30 +02:00 committed by Quim Muntal
parent 4620db72d2
commit 8a6c64f4fe
10 changed files with 6 additions and 17 deletions

View file

@ -59,7 +59,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
r1 uintptr r1 uintptr
nextfd int nextfd int
i int i int
err error
pgrp _C_int pgrp _C_int
cred *Credential cred *Credential
ngroups, groups uintptr ngroups, groups uintptr
@ -99,8 +98,12 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Enable tracing if requested. // Enable tracing if requested.
if sys.Ptrace { if sys.Ptrace {
if err = ptrace(PTRACE_TRACEME, 0, 0, 0); err != nil { if runtime.GOOS == "ios" {
err1 = err.(Errno) err1 = ENOSYS
goto childerror
}
_, _, err1 = rawSyscall6(abi.FuncPCABI0(libc_ptrace_trampoline), PTRACE_TRACEME, 0, 0, 0, 0, 0)
if err1 != 0 {
goto childerror goto childerror
} }
} }

View file

@ -141,12 +141,6 @@ while(<>) {
# without reading the header. # without reading the header.
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
if ((($darwin || ($openbsd && $libc)) && $func =~ /^ptrace(Ptr)?$/)) {
# The ptrace function is called from forkAndExecInChild where stack
# growth is forbidden.
$text .= "//go:nosplit\n"
}
# Go function header. # Go function header.
my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : ""; my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl; $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;

View file

@ -2011,7 +2011,6 @@ func libc_fstatat64_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
if runtime.GOOS == "ios" { if runtime.GOOS == "ios" {
panic("unimplemented") panic("unimplemented")

View file

@ -2011,7 +2011,6 @@ func libc_fstatat_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
if runtime.GOOS == "ios" { if runtime.GOOS == "ios" {
panic("unimplemented") panic("unimplemented")

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {

View file

@ -1839,7 +1839,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
//go:nosplit
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
_, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) _, _, e1 := syscall6(abi.FuncPCABI0(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
if e1 != 0 { if e1 != 0 {