Skip to content

Commit 00d8004

Browse files
committed
unix: match ioctl req argument type to libc type
On Solaris, AIX, and zOS, the req argument of ioctl() is a signed int, not an unsigned long like on other platforms, which means many constants are negative, causing friction when passing them to a uint argument. Correct the signature of these functions to pass the req argument as signed, just like libc. Fixes golang/go#59030. Change-Id: Ia14e92a150f4b5fb9488c5032ca296cb786e9811 Reviewed-on: https://go-review.googlesource.com/c/sys/+/476515 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> Run-TryBot: Jason Donenfeld <Jason@zx2c4.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Nahum Shalman <nahamu@gmail.com>
1 parent d0781cc commit 00d8004

11 files changed

+103
-37
lines changed

unix/ioctl_signed.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2018 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build aix || solaris
6+
// +build aix solaris
7+
8+
package unix
9+
10+
import (
11+
"unsafe"
12+
)
13+
14+
// ioctl itself should not be exposed directly, but additional get/set
15+
// functions for specific types are permissible.
16+
17+
// IoctlSetInt performs an ioctl operation which sets an integer value
18+
// on fd, using the specified request number.
19+
func IoctlSetInt(fd int, req int, value int) error {
20+
return ioctl(fd, req, uintptr(value))
21+
}
22+
23+
// IoctlSetPointerInt performs an ioctl operation which sets an
24+
// integer value on fd, using the specified request number. The ioctl
25+
// argument is called with a pointer to the integer value, rather than
26+
// passing the integer value directly.
27+
func IoctlSetPointerInt(fd int, req int, value int) error {
28+
v := int32(value)
29+
return ioctlPtr(fd, req, unsafe.Pointer(&v))
30+
}
31+
32+
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
33+
//
34+
// To change fd's window size, the req argument should be TIOCSWINSZ.
35+
func IoctlSetWinsize(fd int, req int, value *Winsize) error {
36+
// TODO: if we get the chance, remove the req parameter and
37+
// hardcode TIOCSWINSZ.
38+
return ioctlPtr(fd, req, unsafe.Pointer(value))
39+
}
40+
41+
// IoctlSetTermios performs an ioctl on fd with a *Termios.
42+
//
43+
// The req value will usually be TCSETA or TIOCSETA.
44+
func IoctlSetTermios(fd int, req int, value *Termios) error {
45+
// TODO: if we get the chance, remove the req parameter.
46+
return ioctlPtr(fd, req, unsafe.Pointer(value))
47+
}
48+
49+
// IoctlGetInt performs an ioctl operation which gets an integer value
50+
// from fd, using the specified request number.
51+
//
52+
// A few ioctl requests use the return value as an output parameter;
53+
// for those, IoctlRetInt should be used instead of this function.
54+
func IoctlGetInt(fd int, req int) (int, error) {
55+
var value int
56+
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
57+
return value, err
58+
}
59+
60+
func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
61+
var value Winsize
62+
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
63+
return &value, err
64+
}
65+
66+
func IoctlGetTermios(fd int, req int) (*Termios, error) {
67+
var value Termios
68+
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
69+
return &value, err
70+
}

unix/ioctl.go unix/ioctl_unsigned.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
6-
// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
5+
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
6+
// +build darwin dragonfly freebsd hurd linux netbsd openbsd
77

88
package unix
99

unix/ioctl_zos.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import (
1717

1818
// IoctlSetInt performs an ioctl operation which sets an integer value
1919
// on fd, using the specified request number.
20-
func IoctlSetInt(fd int, req uint, value int) error {
20+
func IoctlSetInt(fd int, req int, value int) error {
2121
return ioctl(fd, req, uintptr(value))
2222
}
2323

2424
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
2525
//
2626
// To change fd's window size, the req argument should be TIOCSWINSZ.
27-
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
27+
func IoctlSetWinsize(fd int, req int, value *Winsize) error {
2828
// TODO: if we get the chance, remove the req parameter and
2929
// hardcode TIOCSWINSZ.
3030
return ioctlPtr(fd, req, unsafe.Pointer(value))
@@ -33,7 +33,7 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
3333
// IoctlSetTermios performs an ioctl on fd with a *Termios.
3434
//
3535
// The req value is expected to be TCSETS, TCSETSW, or TCSETSF
36-
func IoctlSetTermios(fd int, req uint, value *Termios) error {
36+
func IoctlSetTermios(fd int, req int, value *Termios) error {
3737
if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) {
3838
return ENOSYS
3939
}
@@ -47,13 +47,13 @@ func IoctlSetTermios(fd int, req uint, value *Termios) error {
4747
//
4848
// A few ioctl requests use the return value as an output parameter;
4949
// for those, IoctlRetInt should be used instead of this function.
50-
func IoctlGetInt(fd int, req uint) (int, error) {
50+
func IoctlGetInt(fd int, req int) (int, error) {
5151
var value int
5252
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
5353
return value, err
5454
}
5555

56-
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
56+
func IoctlGetWinsize(fd int, req int) (*Winsize, error) {
5757
var value Winsize
5858
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
5959
return &value, err
@@ -62,7 +62,7 @@ func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
6262
// IoctlGetTermios performs an ioctl on fd with a *Termios.
6363
//
6464
// The req value is expected to be TCGETS
65-
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
65+
func IoctlGetTermios(fd int, req int) (*Termios, error) {
6666
var value Termios
6767
if req != TCGETS {
6868
return &value, ENOSYS

unix/syscall_aix.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,8 @@ func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
408408

409409
func (w WaitStatus) TrapCause() int { return -1 }
410410

411-
//sys ioctl(fd int, req uint, arg uintptr) (err error)
412-
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = ioctl
411+
//sys ioctl(fd int, req int, arg uintptr) (err error)
412+
//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = ioctl
413413

414414
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
415415
// There is no way to create a custom fcntl and to keep //sys fcntl easily,

unix/syscall_solaris.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -545,24 +545,24 @@ func Minor(dev uint64) uint32 {
545545
* Expose the ioctl function
546546
*/
547547

548-
//sys ioctlRet(fd int, req uint, arg uintptr) (ret int, err error) = libc.ioctl
549-
//sys ioctlPtrRet(fd int, req uint, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
548+
//sys ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
549+
//sys ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
550550

551-
func ioctl(fd int, req uint, arg uintptr) (err error) {
551+
func ioctl(fd int, req int, arg uintptr) (err error) {
552552
_, err = ioctlRet(fd, req, arg)
553553
return err
554554
}
555555

556-
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
556+
func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
557557
_, err = ioctlPtrRet(fd, req, arg)
558558
return err
559559
}
560560

561-
func IoctlSetTermio(fd int, req uint, value *Termio) error {
561+
func IoctlSetTermio(fd int, req int, value *Termio) error {
562562
return ioctlPtr(fd, req, unsafe.Pointer(value))
563563
}
564564

565-
func IoctlGetTermio(fd int, req uint) (*Termio, error) {
565+
func IoctlGetTermio(fd int, req int) (*Termio, error) {
566566
var value Termio
567567
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
568568
return &value, err
@@ -1079,11 +1079,11 @@ func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags
10791079
return retCl, retData, flags, nil
10801080
}
10811081

1082-
func IoctlSetIntRetInt(fd int, req uint, arg int) (int, error) {
1082+
func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
10831083
return ioctlRet(fd, req, uintptr(arg))
10841084
}
10851085

1086-
func IoctlSetString(fd int, req uint, val string) error {
1086+
func IoctlSetString(fd int, req int, val string) error {
10871087
bs := make([]byte, len(val)+1)
10881088
copy(bs[:len(bs)-1], val)
10891089
err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
@@ -1119,7 +1119,7 @@ func (l *Lifreq) GetLifruUint() uint {
11191119
return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
11201120
}
11211121

1122-
func IoctlLifreq(fd int, req uint, l *Lifreq) error {
1122+
func IoctlLifreq(fd int, req int, l *Lifreq) error {
11231123
return ioctlPtr(fd, req, unsafe.Pointer(l))
11241124
}
11251125

@@ -1130,6 +1130,6 @@ func (s *Strioctl) SetInt(i int) {
11301130
s.Dp = (*int8)(unsafe.Pointer(&i))
11311131
}
11321132

1133-
func IoctlSetStrioctlRetInt(fd int, req uint, s *Strioctl) (int, error) {
1133+
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
11341134
return ioctlPtrRet(fd, req, unsafe.Pointer(s))
11351135
}

unix/syscall_solaris_test.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,13 @@ func TestLifreqGetMTU(t *testing.T) {
405405
if err != nil {
406406
t.Fatalf("could not open udp socket: %v", err)
407407
}
408-
// SIOCGLIFMTU is negative which confuses the compiler if used inline:
409-
// Using "unix.IoctlLifreq(ip_fd, unix.SIOCGLIFMTU, &l)" results in
410-
// "constant -1065850502 overflows uint"
411-
reqnum := int(unix.SIOCGLIFMTU)
412408
var l unix.Lifreq
413409
for link, mtu := range tc {
414410
err = l.SetName(link)
415411
if err != nil {
416412
t.Fatalf("Lifreq.SetName(%q) failed: %v", link, err)
417413
}
418-
if err = unix.IoctlLifreq(ip_fd, uint(reqnum), &l); err != nil {
414+
if err = unix.IoctlLifreq(ip_fd, unix.SIOCGLIFMTU, &l); err != nil {
419415
t.Fatalf("unable to SIOCGLIFMTU: %v", err)
420416
}
421417
m := l.GetLifruUint()

unix/syscall_zos_s390x.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ func (cmsg *Cmsghdr) SetLen(length int) {
212212
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
213213
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
214214
//sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
215-
//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
216-
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL
215+
//sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL
216+
//sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL
217217

218218
//sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A
219219
//sys Chdir(path string) (err error) = SYS___CHDIR_A

unix/zsyscall_aix_ppc.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_aix_ppc64.go

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_solaris_amd64.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

unix/zsyscall_zos_s390x.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)