Skip to content

Commit

Permalink
syscall: use dup3 in forkAndExecInChild on OpenBSD
Browse files Browse the repository at this point in the history
Use dup3(oldfd, newfd, O_CLOEXEC) to atomically duplicate the file
descriptor and mark is as close-on-exec instead of dup2 & fcntl.

The dup3 system call first appeared in OpenBSD 5.7.

Change-Id: Ic06c2c7089dcdbd931ee24e5e8c316879d81474e
Reviewed-on: https://go-review.googlesource.com/c/go/+/389974
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
tklauser authored and pull[bot] committed Mar 8, 2022
1 parent e9ca583 commit 3435758
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 19 deletions.
26 changes: 12 additions & 14 deletions src/syscall/exec_bsd.go
Expand Up @@ -181,18 +181,17 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later.
if pipe < nextfd {
switch runtime.GOOS {
case "netbsd":
if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
_, _, err1 = RawSyscall(_SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
if err1 != 0 {
goto childerror
}
default:
} else {
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
}
if err1 != 0 {
goto childerror
}
pipe = nextfd
nextfd++
Expand All @@ -202,18 +201,17 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if nextfd == pipe { // don't stomp on pipe
nextfd++
}
switch runtime.GOOS {
case "netbsd":
if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
_, _, err1 = RawSyscall(_SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
if err1 != 0 {
goto childerror
}
default:
} else {
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
}
if err1 != 0 {
goto childerror
}
fd[i] = nextfd
nextfd++
Expand Down
23 changes: 19 additions & 4 deletions src/syscall/exec_libc2.go
Expand Up @@ -8,6 +8,7 @@ package syscall

import (
"internal/abi"
"runtime"
"unsafe"
)

Expand Down Expand Up @@ -180,11 +181,18 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later.
if pipe < nextfd {
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_dup2_trampoline), uintptr(pipe), uintptr(nextfd), 0)
if runtime.GOOS == "openbsd" {
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
} else {
_, _, err1 = rawSyscall(dupTrampoline, uintptr(pipe), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
}
if err1 != 0 {
goto childerror
}
rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
pipe = nextfd
nextfd++
}
Expand All @@ -193,11 +201,18 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if nextfd == pipe { // don't stomp on pipe
nextfd++
}
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_dup2_trampoline), uintptr(fd[i]), uintptr(nextfd), 0)
if runtime.GOOS == "openbsd" {
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
} else {
_, _, err1 = rawSyscall(dupTrampoline, uintptr(fd[i]), uintptr(nextfd), 0)
if err1 != 0 {
goto childerror
}
_, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
}
if err1 != 0 {
goto childerror
}
rawSyscall(abi.FuncPCABI0(libc_fcntl_trampoline), uintptr(nextfd), F_SETFD, FD_CLOEXEC)
fd[i] = nextfd
nextfd++
}
Expand Down
2 changes: 2 additions & 0 deletions src/syscall/syscall_darwin.go
Expand Up @@ -17,6 +17,8 @@ import (
"unsafe"
)

var dupTrampoline = abi.FuncPCABI0(libc_dup2_trampoline)

type SockaddrDatalink struct {
Len uint8
Family uint8
Expand Down
1 change: 1 addition & 0 deletions src/syscall/syscall_openbsd.go
Expand Up @@ -136,6 +136,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
//sys Close(fd int) (err error)
//sys Dup(fd int) (nfd int, err error)
//sys Dup2(from int, to int) (err error)
//sys dup3(from int, to int, flags int) (err error)
//sys Fchdir(fd int) (err error)
//sys Fchflags(fd int, flags int) (err error)
//sys Fchmod(fd int, mode uint32) (err error)
Expand Down
2 changes: 2 additions & 0 deletions src/syscall/syscall_openbsd_libc.go
Expand Up @@ -10,6 +10,8 @@ import (
"internal/abi"
)

var dupTrampoline = abi.FuncPCABI0(libc_dup3_trampoline)

func init() {
execveOpenBSD = execve
}
Expand Down
2 changes: 1 addition & 1 deletion src/syscall/syscall_openbsd_mips64.go
Expand Up @@ -4,7 +4,7 @@

package syscall

const _SYS_DUP3 = 0
const _SYS_DUP3 = SYS_DUP3

func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: sec, Nsec: nsec}
Expand Down
14 changes: 14 additions & 0 deletions src/syscall/zsyscall_openbsd_386.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/syscall/zsyscall_openbsd_386.s
Expand Up @@ -69,6 +69,8 @@ TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup(SB)
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
TEXT ·libc_dup3_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup3(SB)
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchdir(SB)
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
Expand Down
14 changes: 14 additions & 0 deletions src/syscall/zsyscall_openbsd_amd64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/syscall/zsyscall_openbsd_amd64.s
Expand Up @@ -69,6 +69,8 @@ TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup(SB)
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
TEXT ·libc_dup3_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup3(SB)
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchdir(SB)
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
Expand Down
14 changes: 14 additions & 0 deletions src/syscall/zsyscall_openbsd_arm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/syscall/zsyscall_openbsd_arm.s
Expand Up @@ -69,6 +69,8 @@ TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup(SB)
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
TEXT ·libc_dup3_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup3(SB)
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchdir(SB)
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
Expand Down
14 changes: 14 additions & 0 deletions src/syscall/zsyscall_openbsd_arm64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/syscall/zsyscall_openbsd_arm64.s
Expand Up @@ -69,6 +69,8 @@ TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup(SB)
TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup2(SB)
TEXT ·libc_dup3_trampoline(SB),NOSPLIT,$0-0
JMP libc_dup3(SB)
TEXT ·libc_fchdir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fchdir(SB)
TEXT ·libc_fchflags_trampoline(SB),NOSPLIT,$0-0
Expand Down

0 comments on commit 3435758

Please sign in to comment.