proc/native: fix syscalls to SYS_PROCESS_VM_READV (and WRITEV) (#3273)

Per https://pkg.go.dev/unsafe#Pointer conversions from unsafe.Pointer
to uintptr are only safe in limited circumstances. In particular only
conversions made in the syscall call are pinned.
Additionally add a call to runtime.KeepAlive to mitigate the bug
described in: https://github.com/golang/go/issues/58351
This commit is contained in:
Alessandro Arzilli 2023-02-14 18:32:13 +01:00 committed by GitHub
parent 19368d8ed3
commit 95e33edf53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 13 deletions

@ -9,8 +9,9 @@ package native
import "C"
import (
"unsafe"
"runtime"
"syscall"
"unsafe"
sys "golang.org/x/sys/unix"
)
@ -60,11 +61,13 @@ func ptraceGetLwpInfo(wpid int) (info sys.PtraceLwpInfoStruct, err error) {
// id may be a PID or an LWPID
func ptraceReadData(id int, addr uintptr, data []byte) (n int, err error) {
defer runtime.KeepAlive(&data[0]) // PIN
return sys.PtraceIO(sys.PIOD_READ_D, id, addr, data, len(data))
}
// id may be a PID or an LWPID
func ptraceWriteData(id int, addr uintptr, data []byte) (n int, err error) {
defer runtime.KeepAlive(&data[0]) // PIN
return sys.PtraceIO(sys.PIOD_WRITE_D, id, addr, data, len(data))
}

@ -69,9 +69,7 @@ func processVmRead(tid int, addr uintptr, data []byte) (int, error) {
len_iov := uint32(len(data))
local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
p_local := uintptr(unsafe.Pointer(&local_iov))
p_remote := uintptr(unsafe.Pointer(&remote_iov))
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), p_local, 1, p_remote, 1, 0)
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0)
if err != syscall.Errno(0) {
return 0, err
}
@ -83,9 +81,7 @@ func processVmWrite(tid int, addr uintptr, data []byte) (int, error) {
len_iov := uint32(len(data))
local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
p_local := uintptr(unsafe.Pointer(&local_iov))
p_remote := uintptr(unsafe.Pointer(&remote_iov))
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), p_local, 1, p_remote, 1, 0)
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0)
if err != syscall.Errno(0) {
return 0, err
}

@ -15,9 +15,7 @@ func processVmRead(tid int, addr uintptr, data []byte) (int, error) {
len_iov := uint64(len(data))
local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
p_local := uintptr(unsafe.Pointer(&local_iov))
p_remote := uintptr(unsafe.Pointer(&remote_iov))
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), p_local, 1, p_remote, 1, 0)
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0)
if err != syscall.Errno(0) {
return 0, err
}
@ -29,9 +27,7 @@ func processVmWrite(tid int, addr uintptr, data []byte) (int, error) {
len_iov := uint64(len(data))
local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
p_local := uintptr(unsafe.Pointer(&local_iov))
p_remote := uintptr(unsafe.Pointer(&remote_iov))
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), p_local, 1, p_remote, 1, 0)
n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0)
if err != syscall.Errno(0) {
return 0, err
}