mirror of https://github.com/golang/go.git
syscall: Fix FD passing on OpenBSD
Fixes #3349. R=bradfitz, dave, minux.ma CC=golang-dev https://golang.org/cl/7383056
This commit is contained in:
parent
d21b1922c6
commit
f853e9aa4e
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux darwin freebsd netbsd
|
||||
// +build linux darwin freebsd netbsd openbsd
|
||||
|
||||
package syscall_test
|
||||
|
||||
|
|
@ -149,3 +149,49 @@ func passFDChild() {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
|
||||
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
|
||||
func TestUnixRightsRoundtrip(t *testing.T) {
|
||||
testCases := [...][][]int{
|
||||
{{42}},
|
||||
{{1, 2}},
|
||||
{{3, 4, 5}},
|
||||
{{}},
|
||||
{{1, 2}, {3, 4, 5}, {}, {7}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
b := []byte{}
|
||||
var n int
|
||||
for _, fds := range testCase {
|
||||
// Last assignment to n wins
|
||||
n = len(b) + syscall.CmsgLen(4*len(fds))
|
||||
b = append(b, syscall.UnixRights(fds...)...)
|
||||
}
|
||||
// Truncate b
|
||||
b = b[:n]
|
||||
|
||||
scms, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||
}
|
||||
if len(scms) != len(testCase) {
|
||||
t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
|
||||
}
|
||||
for i, scm := range scms {
|
||||
gotFds, err := syscall.ParseUnixRights(&scm)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseUnixRights: %v", err)
|
||||
}
|
||||
wantFds := testCase[i]
|
||||
if len(gotFds) != len(wantFds) {
|
||||
t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
|
||||
}
|
||||
for j, fd := range gotFds {
|
||||
if fd != wantFds[j] {
|
||||
t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ package syscall
|
|||
|
||||
import "unsafe"
|
||||
|
||||
// Round the length of a raw sockaddr up to align it propery.
|
||||
// Round the length of a raw sockaddr up to align it properly.
|
||||
func cmsgAlignOf(salen int) int {
|
||||
salign := sizeofPtr
|
||||
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
|
||||
|
|
@ -18,9 +18,6 @@ func cmsgAlignOf(salen int) int {
|
|||
if darwinAMD64 {
|
||||
salign = 4
|
||||
}
|
||||
if salen == 0 {
|
||||
return salign
|
||||
}
|
||||
return (salen + salign - 1) & ^(salign - 1)
|
||||
}
|
||||
|
||||
|
|
@ -50,14 +47,15 @@ type SocketControlMessage struct {
|
|||
// messages.
|
||||
func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
|
||||
var msgs []SocketControlMessage
|
||||
for len(b) >= CmsgLen(0) {
|
||||
h, dbuf, err := socketControlMessageHeaderAndData(b)
|
||||
i := 0
|
||||
for i+CmsgLen(0) <= len(b) {
|
||||
h, dbuf, err := socketControlMessageHeaderAndData(b[i:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := SocketControlMessage{Header: *h, Data: dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]}
|
||||
m := SocketControlMessage{Header: *h, Data: dbuf}
|
||||
msgs = append(msgs, m)
|
||||
b = b[cmsgAlignOf(int(h.Len)):]
|
||||
i += cmsgAlignOf(int(h.Len))
|
||||
}
|
||||
return msgs, nil
|
||||
}
|
||||
|
|
@ -67,7 +65,7 @@ func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
|
|||
if h.Len < SizeofCmsghdr || int(h.Len) > len(b) {
|
||||
return nil, nil, EINVAL
|
||||
}
|
||||
return h, b[cmsgAlignOf(SizeofCmsghdr):], nil
|
||||
return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil
|
||||
}
|
||||
|
||||
// UnixRights encodes a set of open file descriptors into a socket
|
||||
|
|
|
|||
Loading…
Reference in New Issue