From 93c9922d18aeb82498a065f07aec7ad7fa60dfb7 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 10 Jun 2019 09:23:19 -0700 Subject: [PATCH] unix: fix Getdirentries on 32-bit freebsd 12 On freebsd 12, the system call for getdirentries writes 64 bits to *basep, even on 32-bit systems. Accomodate that by providing a uint64 to the system call and copy the base to/from that uint64. The uint64 seems to be a virtual file offset, so failing if the high bits are not zero should be fine for reasonable-sized directories. Update golang/go#32498 Change-Id: I4451894aff4e353c9f009c06ad2fdd5578dfd9f8 Reviewed-on: https://go-review.googlesource.com/c/sys/+/181500 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Tobias Klauser --- unix/syscall_freebsd.go | 18 ++++++++++++++++-- unix/zsyscall_freebsd_386.go | 2 +- unix/zsyscall_freebsd_amd64.go | 2 +- unix/zsyscall_freebsd_arm.go | 2 +- unix/zsyscall_freebsd_arm64.go | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go index f135812a..1b6abe12 100644 --- a/unix/syscall_freebsd.go +++ b/unix/syscall_freebsd.go @@ -362,7 +362,21 @@ func Getdents(fd int, buf []byte) (n int, err error) { func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { if supportsABI(_ino64First) { - return getdirentries_freebsd12(fd, buf, basep) + if unsafe.Sizeof(*basep) == 8 { + return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep))) + } + // The freebsd12 syscall needs a 64-bit base. On 32-bit machines + // we can't just use the basep passed in. See #32498. + var base uint64 = uint64(*basep) + n, err = getdirentries_freebsd12(fd, buf, &base) + *basep = uintptr(base) + if base>>32 != 0 { + // We can't stuff the base back into a uintptr, so any + // future calls would be suspect. Generate an error. + // EIO is allowed by getdirentries. + err = EIO + } + return } // The old syscall entries are smaller than the new. Use 1/4 of the original @@ -555,7 +569,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) //sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) -//sys getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) +//sys getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) //sys Getdtablesize() (size int) //sysnb Getegid() (egid int) //sysnb Geteuid() (uid int) diff --git a/unix/zsyscall_freebsd_386.go b/unix/zsyscall_freebsd_386.go index 80903e47..2707c013 100644 --- a/unix/zsyscall_freebsd_386.go +++ b/unix/zsyscall_freebsd_386.go @@ -1019,7 +1019,7 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) diff --git a/unix/zsyscall_freebsd_amd64.go b/unix/zsyscall_freebsd_amd64.go index cd250ff0..8e3c0cea 100644 --- a/unix/zsyscall_freebsd_amd64.go +++ b/unix/zsyscall_freebsd_amd64.go @@ -1019,7 +1019,7 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) diff --git a/unix/zsyscall_freebsd_arm.go b/unix/zsyscall_freebsd_arm.go index 290a9c2c..641f86a0 100644 --- a/unix/zsyscall_freebsd_arm.go +++ b/unix/zsyscall_freebsd_arm.go @@ -1019,7 +1019,7 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0]) diff --git a/unix/zsyscall_freebsd_arm64.go b/unix/zsyscall_freebsd_arm64.go index c6df9d2e..68fbccf7 100644 --- a/unix/zsyscall_freebsd_arm64.go +++ b/unix/zsyscall_freebsd_arm64.go @@ -1019,7 +1019,7 @@ func getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error) { +func getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { _p0 = unsafe.Pointer(&buf[0])