unix: generate ioctlPtr on Linux with unsafe.Pointer arg

The existing ioctl stubs for all UNIX-like platforms take a value of type
uintptr for the arg parameter. However, arguments which are cast from
unsafe.Pointer to uintptr technically violate the rules for package unsafe.
unsafe only allows a conversion from unsafe.Pointer to uintptr directly
within a call to Syscall.

ioctl is used on all UNIX-like operating systems and each one will have
to be updated accordingly where pointer arguments are passed to system
calls. To remedy this on Linux, we generate a new function called
ioctlPtr which takes a value of type unsafe.Pointer for arg. More
operating systems can be updated in future CLs by folks who have access
to those systems and can run the appropriate code generator.

Updates golang/go#44834

Change-Id: Ia9424be424b3dba91bb44d3a7a12bfb2179f0d86
Reviewed-on: https://go-review.googlesource.com/c/sys/+/340915
Trust: Matt Layher <mdlayher@gmail.com>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matt Layher
2021-08-09 22:13:28 +00:00
parent 894668206c
commit b4502255bf
3 changed files with 36 additions and 18 deletions
+15 -14
View File
@@ -22,30 +22,30 @@ func IoctlRetInt(fd int, req uint) (int, error) {
func IoctlGetUint32(fd int, req uint) (uint32, error) { func IoctlGetUint32(fd int, req uint) (uint32, error) {
var value uint32 var value uint32
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return value, err return value, err
} }
func IoctlGetRTCTime(fd int) (*RTCTime, error) { func IoctlGetRTCTime(fd int) (*RTCTime, error) {
var value RTCTime var value RTCTime
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlSetRTCTime(fd int, value *RTCTime) error { func IoctlSetRTCTime(fd int, value *RTCTime) error {
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) err := ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error { func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value))) err := ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
@@ -61,7 +61,7 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO} value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO}
ifrd := ifr.SetData(unsafe.Pointer(&value)) ifrd := ifr.SetData(unsafe.Pointer(&value))
err = ioctl(fd, SIOCETHTOOL, uintptr(unsafe.Pointer(&ifrd))) err = ioctlPtr(fd, SIOCETHTOOL, unsafe.Pointer(&ifrd))
runtime.KeepAlive(ifrd) runtime.KeepAlive(ifrd)
return &value, err return &value, err
} }
@@ -71,7 +71,7 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
var value WatchdogInfo var value WatchdogInfo
err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value))
return &value, err return &value, err
} }
@@ -79,6 +79,7 @@ func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
// more information, see: // more information, see:
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlWatchdogKeepalive(fd int) error { func IoctlWatchdogKeepalive(fd int) error {
// arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr.
return ioctl(fd, WDIOC_KEEPALIVE, 0) return ioctl(fd, WDIOC_KEEPALIVE, 0)
} }
@@ -86,7 +87,7 @@ func IoctlWatchdogKeepalive(fd int) error {
// range of data conveyed in value to the file associated with the file // range of data conveyed in value to the file associated with the file
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details. // descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value))) err := ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
@@ -139,7 +140,7 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
rawinfo.Reserved = value.Info[i].Reserved rawinfo.Reserved = value.Info[i].Reserved
} }
err := ioctl(srcFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(&buf[0]))) err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0]))
// Output // Output
for i := range value.Info { for i := range value.Info {
@@ -157,31 +158,31 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
} }
func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error { func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error {
err := ioctl(fd, HIDIOCGRDESC, uintptr(unsafe.Pointer(value))) err := ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value))
runtime.KeepAlive(value) runtime.KeepAlive(value)
return err return err
} }
func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) { func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) {
var value HIDRawDevInfo var value HIDRawDevInfo
err := ioctl(fd, HIDIOCGRAWINFO, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlHIDGetRawName(fd int) (string, error) { func IoctlHIDGetRawName(fd int) (string, error) {
var value [_HIDIOCGRAWNAME_LEN]byte var value [_HIDIOCGRAWNAME_LEN]byte
err := ioctl(fd, _HIDIOCGRAWNAME, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err return ByteSliceToString(value[:]), err
} }
func IoctlHIDGetRawPhys(fd int) (string, error) { func IoctlHIDGetRawPhys(fd int) (string, error) {
var value [_HIDIOCGRAWPHYS_LEN]byte var value [_HIDIOCGRAWPHYS_LEN]byte
err := ioctl(fd, _HIDIOCGRAWPHYS, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err return ByteSliceToString(value[:]), err
} }
func IoctlHIDGetRawUniq(fd int) (string, error) { func IoctlHIDGetRawUniq(fd int) (string, error) {
var value [_HIDIOCGRAWUNIQ_LEN]byte var value [_HIDIOCGRAWUNIQ_LEN]byte
err := ioctl(fd, _HIDIOCGRAWUNIQ, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err return ByteSliceToString(value[:]), err
} }
+11 -4
View File
@@ -66,11 +66,18 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
return fchmodat(dirfd, path, mode) return fchmodat(dirfd, path, mode)
} }
//sys ioctl(fd int, req uint, arg uintptr) (err error) //sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL
// ioctl itself should not be exposed directly, but additional get/set // ioctl itself should not be exposed directly, but additional get/set functions
// functions for specific types are permissible. // for specific types are permissible. These are defined in ioctl.go and
// These are defined in ioctl.go and ioctl_linux.go. // ioctl_linux.go.
//
// The third argument to ioctl is often a pointer but sometimes an integer.
// Callers should use ioctlPtr when the third argument is a pointer and ioctl
// when the third argument is an integer.
//
// TODO: some existing code incorrectly uses ioctl when it should use ioctlPtr.
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
+10
View File
@@ -48,6 +48,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
// 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
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) { func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
var _p0 *byte var _p0 *byte
_p0, err = BytePtrFromString(oldpath) _p0, err = BytePtrFromString(oldpath)