Skip to content

Commit dbd69c5

Browse files
committed
Fix ptsname() for big-endian architectures
On big-endian architectures unix.IoctlGetInt() leads to a wrong result because a 32 bit value is stored into a 64 bit buffer. When dereferencing the result is left shifted by 32. Without this patch ptsname() returns a wrong path from the second pty onwards. To protect syscalls against re-arranging by the GC the conversion from unsafe.Pointer to uintptr must occur in the Syscall expression itself. See the documentation of the unsafe package for details. Signed-off-by: Peter Morjan <[email protected]>
1 parent 84eeaae commit dbd69c5

1 file changed

Lines changed: 7 additions & 11 deletions

File tree

tc_linux.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,21 @@ const (
1313
cmdTcSet = unix.TCSETS
1414
)
1515

16-
func ioctl(fd, flag, data uintptr) error {
17-
if _, _, err := unix.Syscall(unix.SYS_IOCTL, fd, flag, data); err != 0 {
18-
return err
19-
}
20-
return nil
21-
}
22-
2316
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
2417
// unlockpt should be called before opening the slave side of a pty.
2518
func unlockpt(f *os.File) error {
2619
var u int32
27-
return ioctl(f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
20+
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 {
21+
return err
22+
}
23+
return nil
2824
}
2925

3026
// ptsname retrieves the name of the first available pts for the given master.
3127
func ptsname(f *os.File) (string, error) {
32-
n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN)
33-
if err != nil {
28+
var u uint32
29+
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 {
3430
return "", err
3531
}
36-
return fmt.Sprintf("/dev/pts/%d", n), nil
32+
return fmt.Sprintf("/dev/pts/%d", u), nil
3733
}

0 commit comments

Comments
 (0)