mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-03 15:47:35 -04:00
unix: drop dummy byte for oob in unixgram SendmsgN
This commit relaxes SendmsgN behavior of introducing a dummy 1-byte payload when sending ancillary-only messages. The fake payload is not needed for SOCK_DGRAM type sockets, and actually breaks interoperability with other fd-passing software (journald is one known example). This introduces an additional check to avoid injecting dummy payload in such case. Backport of https://go.googlesource.com/go/+/93da0b6e66f24c4c307e0df37ceb102a33306174 Full reference at https:/golang.org/issue/6476#issue-51285243 Change-Id: I7cf00a1c7cde75fe62e00b98ccba6ac8469b0493 Reviewed-on: https://go-review.googlesource.com/60190 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
committed by
Ian Lance Taylor
parent
ab9e364efd
commit
bb24a47a89
+19
-4
@@ -21,7 +21,21 @@ import (
|
|||||||
// sockets. The SO_PASSCRED socket option is enabled on the sending
|
// sockets. The SO_PASSCRED socket option is enabled on the sending
|
||||||
// socket for this to work.
|
// socket for this to work.
|
||||||
func TestSCMCredentials(t *testing.T) {
|
func TestSCMCredentials(t *testing.T) {
|
||||||
fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
|
socketTypeTests := []struct {
|
||||||
|
socketType int
|
||||||
|
dataLen int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
unix.SOCK_STREAM,
|
||||||
|
1,
|
||||||
|
}, {
|
||||||
|
unix.SOCK_DGRAM,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range socketTypeTests {
|
||||||
|
fds, err := unix.Socketpair(unix.AF_LOCAL, tt.socketType, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Socketpair: %v", err)
|
t.Fatalf("Socketpair: %v", err)
|
||||||
}
|
}
|
||||||
@@ -74,7 +88,7 @@ func TestSCMCredentials(t *testing.T) {
|
|||||||
ucred.Gid = uint32(os.Getgid())
|
ucred.Gid = uint32(os.Getgid())
|
||||||
oob := unix.UnixCredentials(&ucred)
|
oob := unix.UnixCredentials(&ucred)
|
||||||
|
|
||||||
// this is going to send a dummy byte
|
// On SOCK_STREAM, this is internally going to send a dummy byte
|
||||||
n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
|
n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("WriteMsgUnix: %v", err)
|
t.Fatalf("WriteMsgUnix: %v", err)
|
||||||
@@ -94,8 +108,8 @@ func TestSCMCredentials(t *testing.T) {
|
|||||||
if flags != 0 {
|
if flags != 0 {
|
||||||
t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
|
t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
|
||||||
}
|
}
|
||||||
if n != 1 {
|
if n != tt.dataLen {
|
||||||
t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
|
t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen)
|
||||||
}
|
}
|
||||||
if oobn2 != oobn {
|
if oobn2 != oobn {
|
||||||
// without SO_PASSCRED set on the socket, ReadMsgUnix will
|
// without SO_PASSCRED set on the socket, ReadMsgUnix will
|
||||||
@@ -119,3 +133,4 @@ func TestSCMCredentials(t *testing.T) {
|
|||||||
t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
|
t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
+12
-2
@@ -931,8 +931,13 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
|
|||||||
}
|
}
|
||||||
var dummy byte
|
var dummy byte
|
||||||
if len(oob) > 0 {
|
if len(oob) > 0 {
|
||||||
|
var sockType int
|
||||||
|
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
// receive at least one normal byte
|
// receive at least one normal byte
|
||||||
if len(p) == 0 {
|
if sockType != SOCK_DGRAM && len(p) == 0 {
|
||||||
iov.Base = &dummy
|
iov.Base = &dummy
|
||||||
iov.SetLen(1)
|
iov.SetLen(1)
|
||||||
}
|
}
|
||||||
@@ -978,8 +983,13 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
|
|||||||
}
|
}
|
||||||
var dummy byte
|
var dummy byte
|
||||||
if len(oob) > 0 {
|
if len(oob) > 0 {
|
||||||
|
var sockType int
|
||||||
|
sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
// send at least one normal byte
|
// send at least one normal byte
|
||||||
if len(p) == 0 {
|
if sockType != SOCK_DGRAM && len(p) == 0 {
|
||||||
iov.Base = &dummy
|
iov.Base = &dummy
|
||||||
iov.SetLen(1)
|
iov.SetLen(1)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user