Esempio n. 1
0
func RemoteRecvCredentials(conn *net.UnixConn) (uint32, uint32, error) {
	err := syscall.SetsockoptInt(sysfd(conn), syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)

	if err != nil {
		return 0, 0, err
	}

	oob := make([]byte, len(syscall.UnixCredentials(&syscall.Ucred{})))

	_, _, _, _, err = conn.ReadMsgUnix(nil, oob)

	if err != nil {
		return 0, 0, err
	}

	scm, err := syscall.ParseSocketControlMessage(oob)

	if err != nil {
		return 0, 0, err
	}

	ucred, err := syscall.ParseUnixCredentials(&scm[0])

	if err != nil {
		return 0, 0, err
	}

	return ucred.Uid, ucred.Gid, nil
}
Esempio n. 2
0
func (fd *Fd) readFrom(c *net.UnixConn) error {
	var b []byte
	oob := make([]byte, 16)
	_, oobn, _, _, err := c.ReadMsgUnix(b, oob)
	if err != nil {
		return err
	}
	if oobn == 0 {
		return errors.New("error reading oob")
	}
	oob = oob[:oobn]

	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return err
	}
	if len(scms) != 1 {
		return fmt.Errorf("expected 1 SocketControlMessage, got %d", len(scms))
	}
	scm := scms[0]
	fds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return nil
	}
	if len(fds) != 1 {
		return fmt.Errorf("expected 1 fd, got %d", len(fds))
	}
	*fd = Fd(fds[0])
	return nil
}
Esempio n. 3
0
func extractFds(oob []byte) (fds []int) {
	// Grab forklock to make sure no forks accidentally inherit the new
	// fds before they are made CLOEXEC
	// There is a slight race condition between ReadMsgUnix returns and
	// when we grap the lock, so this is not perfect. Unfortunately
	// There is no way to pass MSG_CMSG_CLOEXEC to recvmsg() nor any
	// way to implement non-blocking i/o in go, so this is hard to fix.
	syscall.ForkLock.Lock()
	defer syscall.ForkLock.Unlock()
	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return
	}
	for _, scm := range scms {
		gotFds, err := syscall.ParseUnixRights(&scm)
		if err != nil {
			continue
		}
		fds = append(fds, gotFds...)

		for _, fd := range fds {
			syscall.CloseOnExec(fd)
		}
	}
	return
}
Esempio n. 4
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	if len(b) == 0 {
		return nil, nil
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != ianaProtocolIP {
			continue
		}
		switch m.Header.Type {
		case syscall.IP_RECVTTL:
			cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
		case syscall.IP_RECVDSTADDR:
			v := m.Data[:4]
			cm.Dst = net.IPv4(v[0], v[1], v[2], v[3])
		case syscall.IP_RECVIF:
			sadl := (*syscall.SockaddrDatalink)(unsafe.Pointer(&m.Data[0]))
			cm.IfIndex = int(sadl.Index)
		}
	}
	return cm, nil
}
Esempio n. 5
0
func (s *OOBUnixConn) Read(p []byte) (n int, err error) {
	var oob [OOBMaxLength]byte
	n, oobn, _, _, err := s.ReadMsgUnix(p, oob[:])
	if err == nil && n > 0 && oobn > 0 {
		scm, err := syscall.ParseSocketControlMessage(oob[0:oobn])
		if err != nil {
			return n, err
		}
		s.m.Lock()
		for _, m := range scm {
			if m.Header.Level != syscall.SOL_SOCKET {
				continue
			}
			switch m.Header.Type {
			case syscall.SCM_RIGHTS:
				if fds, err := syscall.ParseUnixRights(&m); err == nil {
					for _, fd := range fds {
						// Note: We wrap the raw FDs inside an os.File just
						// once, early, to prevent double-free or leaking FDs.
						f := NewFile(fd)
						s.recvFiles = append(s.recvFiles, f)
					}
				}
			}
		}
		s.m.Unlock()
	}
	return n, err
}
Esempio n. 6
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	if len(b) == 0 {
		return nil, nil
	}
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != iana.ProtocolIP {
			continue
		}
		switch int(m.Header.Type) {
		case ctlOpts[ctlTTL].name:
			ctlOpts[ctlTTL].parse(cm, m.Data[:])
		case ctlOpts[ctlDst].name:
			ctlOpts[ctlDst].parse(cm, m.Data[:])
		case ctlOpts[ctlInterface].name:
			ctlOpts[ctlInterface].parse(cm, m.Data[:])
		case ctlOpts[ctlPacketInfo].name:
			ctlOpts[ctlPacketInfo].parse(cm, m.Data[:])
		}
	}
	return cm, nil
}
Esempio n. 7
0
func (r *FDReader) Read(b []byte) (int, error) {
	oob := make([]byte, 32)
	n, oobn, _, _, err := r.conn.ReadMsgUnix(b, oob)
	if err != nil {
		if n < 0 {
			n = 0
		}
		return n, err
	}
	if oobn > 0 {
		messages, err := syscall.ParseSocketControlMessage(oob[:oobn])
		if err != nil {
			return n, err
		}
		for _, m := range messages {
			fds, err := syscall.ParseUnixRights(&m)
			if err != nil {
				return n, err
			}

			// Set the CLOEXEC flag on the FDs so they won't be leaked into future forks
			for _, fd := range fds {
				if _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_SETFD, syscall.FD_CLOEXEC); errno != 0 {
					return n, errno
				}

				r.FDs[r.fdCount] = fd
				r.fdCount++
			}
		}
	}

	return n, nil
}
Esempio n. 8
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	if len(b) == 0 {
		return nil, nil
	}
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != ianaProtocolIPv6 {
			continue
		}
		switch m.Header.Type {
		case syscall.IPV6_TCLASS:
			cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
		case syscall.IPV6_HOPLIMIT:
			cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
		case syscall.IPV6_PKTINFO:
			pi := (*syscall.Inet6Pktinfo)(unsafe.Pointer(&m.Data[0]))
			cm.Dst = pi.Addr[:]
			cm.IfIndex = int(pi.Ifindex)
		case syscall.IPV6_PATHMTU:
			mi := (*syscall.IPv6MTUInfo)(unsafe.Pointer(&m.Data[0]))
			cm.Dst = mi.Addr.Addr[:]
			cm.IfIndex = int(mi.Addr.Scope_id)
			cm.MTU = int(mi.Mtu)
		}
	}
	return cm, nil
}
Esempio n. 9
0
func mount(dir string, ready chan<- struct{}, errp *error) (fusefd *os.File, err error) {
	// linux mount is never delayed
	close(ready)

	fds, err := syscall.Socketpair(syscall.AF_FILE, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, fmt.Errorf("socketpair error: %v", err)
	}
	defer syscall.Close(fds[0])
	defer syscall.Close(fds[1])

	cmd := exec.Command("fusermount", "--", dir)
	cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")

	writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
	defer writeFile.Close()
	cmd.ExtraFiles = []*os.File{writeFile}

	out, err := cmd.CombinedOutput()
	if len(out) > 0 || err != nil {
		return nil, fmt.Errorf("fusermount: %q, %v", out, err)
	}

	readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads")
	defer readFile.Close()
	c, err := net.FileConn(readFile)
	if err != nil {
		return nil, fmt.Errorf("FileConn from fusermount socket: %v", err)
	}
	defer c.Close()

	uc, ok := c.(*net.UnixConn)
	if !ok {
		return nil, fmt.Errorf("unexpected FileConn type; expected UnixConn, got %T", c)
	}

	buf := make([]byte, 32) // expect 1 byte
	oob := make([]byte, 32) // expect 24 bytes
	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, fmt.Errorf("ParseSocketControlMessage: %v", err)
	}
	if len(scms) != 1 {
		return nil, fmt.Errorf("expected 1 SocketControlMessage; got scms = %#v", scms)
	}
	scm := scms[0]
	gotFds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return nil, fmt.Errorf("syscall.ParseUnixRights: %v", err)
	}
	if len(gotFds) != 1 {
		return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds)
	}
	f := os.NewFile(uintptr(gotFds[0]), "/dev/fuse")
	return f, nil
}
Esempio n. 10
0
func readRequest(c *net.UnixConn) (*Request, error) {
	var l uint32
	err := binary.Read(c, binary.BigEndian, &l)
	length := int(l)
	if err != nil {
		return nil, err
	}
	payload := make([]byte, length)
	n, err := c.Read(payload)
	if err != nil {
		return nil, err
	} else if n != length {
		return nil, fmt.Errorf("Payload was %d bytes rather than reported size of %d", n, length)
	}
	req := &Request{}
	err = json.Unmarshal(payload, req)
	if err != nil {
		return nil, err
	}
	if !req.HasFds {
		return req, nil
	}

	payload = make([]byte, 1)
	// TODO: does this buffer need to be configurable?
	oob := make([]byte, 8192)
	n, oobn, _, _, err := c.ReadMsgUnix(payload, oob)
	if err != nil && err != io.EOF {
		return nil, err
	}
	if n != 1 {
		return nil, fmt.Errorf("Error reading OOB filedescriptors")
	}
	oob = oob[0:oobn]
	scm, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return nil, fmt.Errorf("Error parsing socket control message: %v", err)
	}
	var fds []int
	for i := 0; i < len(scm); i++ {
		tfds, err := syscall.ParseUnixRights(&scm[i])
		if err == syscall.EINVAL {
			continue // Wasn't a UnixRights Control Message
		} else if err != nil {
			return nil, fmt.Errorf("Error parsing unix rights: %v", err)
		}
		fds = append(fds, tfds...)
	}
	if len(fds) == 0 {
		return nil, fmt.Errorf("Failed to receive any FDs on a request with HasFds == true")
	}
	req.ReceivedFds = fds
	return req, nil
}
Esempio n. 11
0
func RetrieveOriginalDest(oob []byte) v2net.Destination {
	msgs, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return nil
	}
	for _, msg := range msgs {
		if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_ORIGDSTADDR {
			ip := v2net.IPAddress(msg.Data[4:8])
			port := v2net.PortFromBytes(msg.Data[2:4])
			return v2net.UDPDestination(ip, port)
		}
	}
	return nil
}
Esempio n. 12
0
func (c *Conn) ReadMessage() (m *Message, err error) {
	h, err := c.readHeader()
	if err != nil {
		return
	}

	log.Printf("ReadMessage: header = %s", h)

	m = &Message{
		object: h.object(),
		opcode: h.opcode(),
	}

	if h.size() == 0 {
		return
	}

	p := make([]byte, h.size())
	oob := make([]byte, 32)
	n, oobn, _, _, err := c.c.ReadMsgUnix(p, oob)
	if err != nil {
		return
	}
	if uint16(n) != h.size() {
		err = fmt.Errorf("expected %d bytes, got %d", h.size(), n)
		return
	}

	log.Printf("ReadMessage: n = %d, oobn = %d", n, oobn)

	m.p = bytes.NewBuffer(p)

	if oobn == 0 {
		return
	}

	oob = oob[:oobn]
	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return
	}
	if len(scms) != 1 {
		err = fmt.Errorf("expected 1 SocketControlMessage, got %d", len(scms))
		return
	}
	scm := scms[0]
	m.fds, err = syscall.ParseUnixRights(&scm)
	return
}
Esempio n. 13
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	if len(b) == 0 {
		return nil, nil
	}
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != ianaProtocolIP {
			continue
		}
		cm.parseControlMessage(&m)
	}
	return cm, nil
}
Esempio n. 14
0
// readIPv6Packet reads an IPv6 packet. For IPv6, the Read* functions do not
// include the IP header, so the HOPLIMIT and destination address are read from
// the control message data (see RFCs 3542 and 2292). The source address is
// taken from the ReadMsgIP return values.
func (c *IPHAConn) readIPv6Packet() (*packet, error) {
	b := recvBuffer
	oob := oobBuffer
	n, oobn, _, raddr, err := c.recvConn.ReadMsgIP(b, oob)
	if err != nil {
		return nil, err
	}
	scm, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, err
	}
	var dst net.IP
	var ttl uint8
	haveTTL := false
	for _, sc := range scm {
		if sc.Header.Level != syscall.IPPROTO_IPV6 {
			continue
		}
		switch sc.Header.Type {
		case syscall.IPV6_2292HOPLIMIT:
			if len(sc.Data) == 0 {
				return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Invalid HOPLIMIT")
			}
			ttl = sc.Data[0]
			haveTTL = true
		case syscall.IPV6_2292PKTINFO:
			if len(sc.Data) < 16 {
				return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Invalid destination address")
			}
			dst = net.IP(sc.Data[:16])
		}
	}

	if !haveTTL {
		return nil, fmt.Errorf("IPHAConn.readIPv6Packet: HOPLIMIT not found")
	}
	if dst == nil {
		return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Destination address not found")
	}
	return &packet{
		src:     raddr.IP,
		dst:     dst,
		ttl:     ttl,
		payload: b[:n],
	}, nil
}
Esempio n. 15
0
func (t *unixTransport) ReadNullByte() error {
	var oobBuf [4096]byte
	res := []byte{0}

	// There is currently no way to get at the underlying fd of a UnixConn, so
	// we can't set SO_PASSCRED on it. We can use File() to get a copy of it though.
	// Unfortunately that will not allow us to ReadMsgUnix, so we have to do that
	// manually
	file, err := t.File()
	if err != nil {
		return err
	}

	err = syscall.SetsockoptInt(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
	if err != nil {
		return err
	}

	n, oobn, flags, _, err := readMsg(file, res, oobBuf[:])
	if err != nil {
		return err
	}

	if n == 0 {
		return io.ErrUnexpectedEOF
	}

	if flags&syscall.MSG_CTRUNC != 0 {
		return errors.New("dbus: control data truncated")
	}

	msgs, err := syscall.ParseSocketControlMessage(oobBuf[:oobn])
	if err != nil {
		return err
	}

	for _, msg := range msgs {
		cred, _ := syscall.ParseUnixCredentials(&msg)
		if cred != nil {
			t.hasPeerUid = true
			t.peerUid = cred.Uid
		}
	}

	return nil
}
Esempio n. 16
0
func readData(conn net.Conn) ([]Fd, int, error) {
	var b [2048]byte
	var oob [2048]byte
	var response Response

	n, oobn, _, _, err := conn.(*net.UnixConn).ReadMsgUnix(b[:], oob[:])
	if err != nil {
		return nil, 0, fmt.Errorf("unix_socket: failed to read unix msg: %s (read: %d, %d)", err, n, oobn)
	}

	if n > 0 {
		err := json.Unmarshal(b[:n], &response)
		if err != nil {
			return nil, 0, fmt.Errorf("unix_socket: Unmarshal failed: %s", err)
		}

		if response.ErrMessage != "" {
			return nil, 0, errors.New(response.ErrMessage)
		}
	} else {
		return nil, 0, errors.New("unix_socket: No response received")
	}

	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, 0, fmt.Errorf("unix_socket: failed to parse socket control message: %s", err)
	}

	if len(scms) < 1 {
		return nil, 0, fmt.Errorf("unix_socket: no socket control messages sent")
	}

	scm := scms[0]
	fds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return nil, 0, fmt.Errorf("unix_socket: failed to parse unix rights: %s", err)
	}

	files := make([]Fd, len(fds))
	for i, fd := range fds {
		files[i] = os.NewFile(uintptr(fd), fmt.Sprintf("/dev/fake-fd-%d", i))
	}

	return files, response.Pid, nil
}
Esempio n. 17
0
func extractFileDescriptorFromOOB(oob []byte) (int, error) {
	scms, err := syscall.ParseSocketControlMessage(oob)
	if err != nil {
		return -1, err
	}
	if len(scms) != 1 {
		return -1, errors.New(fmt.Sprintf("expected 1 SocketControlMessage; got scms = %#v", scms))
	}
	scm := scms[0]
	gotFds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return -1, err
	}
	if len(gotFds) != 1 {
		return -1, errors.New(fmt.Sprintf("wanted 1 fd; got %#v", gotFds))
	}
	return gotFds[0], nil
}
Esempio n. 18
0
// 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)
				}
			}
		}
	}
}
Esempio n. 19
0
File: fd.go Progetto: ftrvxmtrx/fd
// Get receives file descriptors from a Unix domain socket.
//
// Num specifies the expected number of file descriptors in one message.
// Internal files' names to be assigned are specified via optional filenames
// argument.
//
// You need to close all files in the returned slice. The slice can be
// non-empty even if this function returns an error.
//
// Use net.FileConn() if you're receiving a network connection.
func Get(via *net.UnixConn, num int, filenames []string) ([]*os.File, error) {
	if num < 1 {
		return nil, nil
	}

	// get the underlying socket
	viaf, err := via.File()
	if err != nil {
		return nil, err
	}
	socket := int(viaf.Fd())
	defer viaf.Close()

	// recvmsg
	buf := make([]byte, syscall.CmsgSpace(num*4))
	_, _, _, _, err = syscall.Recvmsg(socket, nil, buf, 0)
	if err != nil {
		return nil, err
	}

	// parse control msgs
	var msgs []syscall.SocketControlMessage
	msgs, err = syscall.ParseSocketControlMessage(buf)

	// convert fds to files
	res := make([]*os.File, 0, len(msgs))
	for i := 0; i < len(msgs) && err == nil; i++ {
		var fds []int
		fds, err = syscall.ParseUnixRights(&msgs[i])

		for fi, fd := range fds {
			var filename string
			if fi < len(filenames) {
				filename = filenames[fi]
			}

			res = append(res, os.NewFile(uintptr(fd), filename))
		}
	}

	return res, err
}
Esempio n. 20
0
func ReadWaylandMessage(conn *net.UnixConn) (*Message, error) {
	var buf [8]byte
	msg := Message{}
	control := make([]byte, 24)

	n, oobn, _, _, err := conn.ReadMsgUnix(buf[:], control)
	if err != nil {
		return nil, err
	}
	if n != 8 {
		return nil, errors.New("Unable to read message header.")
	}
	if oobn > 0 {
		if oobn > len(control) {
			panic("Unsufficient control msg buffer")
		}
		msg.control_msgs, err = syscall.ParseSocketControlMessage(control)
		if err != nil {
			panic(fmt.Sprintf("Control message parse error: %s", err.Error()))
		}
	}

	msg.Id = ProxyId(binary.LittleEndian.Uint32(buf[0:4]))
	msg.Opcode = uint32(binary.LittleEndian.Uint16(buf[4:6]))
	msg.size = uint32(binary.LittleEndian.Uint16(buf[6:8]))

	// subtract 8 bytes from header
	data := make([]byte, msg.size-8)

	n, err = conn.Read(data)
	if err != nil {
		return nil, err
	}
	if n != int(msg.size)-8 {
		return nil, errors.New("Invalid message size.")
	}
	msg.data = bytes.NewBuffer(data)

	return &msg, nil
}
Esempio n. 21
0
func ReadFile(c *net.UnixConn, timeout time.Duration) (*os.File, error) {
	oob := make([]byte, 64)

	if timeout > 0 {
		deadline := time.Now().Add(timeout)
		if err := c.SetReadDeadline(deadline); err != nil {
			return nil, err
		}
	}

	_, oobn, flags, _, err := c.ReadMsgUnix(nil, oob)
	if err != nil {
		return nil, err
	}
	if flags != 0 || oobn <= 0 {
		panic("ReadMsgUnix: flags != 0 || oobn <= 0")
	}

	// file descriptors are now open in this process

	scm, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, err
	}
	if len(scm) != 1 {
		panic("invalid scm message")
	}

	fds, err := syscall.ParseUnixRights(&scm[0])
	if err != nil {
		return nil, err
	}
	if len(fds) != 1 {
		panic("invalid scm message")
	}

	return os.NewFile(uintptr(fds[0]), ""), nil
}
Esempio n. 22
0
File: message.go Progetto: Safe3/oz
func (m *Message) parseControlData(data []byte) error {
	cmsgs, err := syscall.ParseSocketControlMessage(data)
	if err != nil {
		return err
	}
	for _, cmsg := range cmsgs {
		switch cmsg.Header.Type {
		case syscall.SCM_CREDENTIALS:
			cred, err := syscall.ParseUnixCredentials(&cmsg)
			if err != nil {
				return err
			}
			m.Ucred = cred
		case syscall.SCM_RIGHTS:
			fds, err := syscall.ParseUnixRights(&cmsg)
			if err != nil {
				return err
			}
			m.Fds = fds
		}
	}
	return nil
}
Esempio n. 23
0
func RecvFd(conn *net.UnixConn) (*os.File, error) {
	buf := make([]byte, 32)
	oob := make([]byte, 32)
	_, oobn, _, _, err := conn.ReadMsgUnix(buf, oob)
	if err != nil {
		return nil, fmt.Errorf("recvfd: err %v", err)
	}
	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, fmt.Errorf("recvfd: ParseSocketControlMessage failed %v", err)
	}
	if len(scms) != 1 {
		return nil, fmt.Errorf("recvfd: SocketControlMessage count not 1: %v", len(scms))
	}
	scm := scms[0]
	fds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return nil, fmt.Errorf("recvfd: ParseUnixRights failed %v", err)
	}
	if len(fds) != 1 {
		return nil, fmt.Errorf("recvfd: fd count not 1: %v", len(fds))
	}
	return os.NewFile(uintptr(fds[0]), "passed-fd"), nil
}
Esempio n. 24
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	if len(b) == 0 {
		return nil, nil
	}
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != ianaProtocolIPv6 {
			continue
		}
		switch m.Header.Type {
		case sysSockopt2292HopLimit:
			cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
		case sysSockopt2292PacketInfo:
			pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
			cm.IfIndex = int(pi.IfIndex)
			cm.Dst = pi.IP[:]
		}
	}
	return cm, nil
}
Esempio n. 25
0
func parseControlMessage(b []byte) (*ControlMessage, error) {
	cmsgs, err := syscall.ParseSocketControlMessage(b)
	if err != nil {
		return nil, os.NewSyscallError("parse socket control message", err)
	}
	if len(b) == 0 {
		return nil, nil
	}
	cm := &ControlMessage{}
	for _, m := range cmsgs {
		if m.Header.Level != ianaProtocolIP {
			continue
		}
		switch m.Header.Type {
		case syscall.IP_TTL:
			cm.TTL = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
		case syscall.IP_PKTINFO:
			pi := (*syscall.Inet4Pktinfo)(unsafe.Pointer(&m.Data[0]))
			cm.IfIndex = int(pi.Ifindex)
			cm.Dst = net.IPv4(pi.Addr[0], pi.Addr[1], pi.Addr[2], pi.Addr[3])
		}
	}
	return cm, nil
}
Esempio n. 26
0
// TestSCMCredentials tests the sending and receiving of credentials
// (PID, UID, GID) in an ancillary message between two UNIX
// sockets. The SO_PASSCRED socket option is enabled on the sending
// socket for this to work.
func TestSCMCredentials(t *testing.T) {
	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
	if err != nil {
		t.Fatalf("Socketpair: %v", err)
	}
	defer syscall.Close(fds[0])
	defer syscall.Close(fds[1])

	err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
	if err != nil {
		t.Fatalf("SetsockoptInt: %v", err)
	}

	srv, err := net.FileConn(os.NewFile(uintptr(fds[0]), ""))
	if err != nil {
		t.Errorf("FileConn: %v", err)
		return
	}
	defer srv.Close()

	cli, err := net.FileConn(os.NewFile(uintptr(fds[1]), ""))
	if err != nil {
		t.Errorf("FileConn: %v", err)
		return
	}
	defer cli.Close()

	var ucred syscall.Ucred
	if os.Getuid() != 0 {
		ucred.Pid = int32(os.Getpid())
		ucred.Uid = 0
		ucred.Gid = 0
		oob := syscall.UnixCredentials(&ucred)
		_, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
		if err.(*net.OpError).Err != syscall.EPERM {
			t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
		}
	}

	ucred.Pid = int32(os.Getpid())
	ucred.Uid = uint32(os.Getuid())
	ucred.Gid = uint32(os.Getgid())
	oob := syscall.UnixCredentials(&ucred)

	// this is going to send a dummy byte
	n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
	if err != nil {
		t.Fatalf("WriteMsgUnix: %v", err)
	}
	if n != 0 {
		t.Fatalf("WriteMsgUnix n = %d, want 0", n)
	}
	if oobn != len(oob) {
		t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
	}

	oob2 := make([]byte, 10*len(oob))
	n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
	if err != nil {
		t.Fatalf("ReadMsgUnix: %v", err)
	}
	if flags != 0 {
		t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
	}
	if n != 1 {
		t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
	}
	if oobn2 != oobn {
		// without SO_PASSCRED set on the socket, ReadMsgUnix will
		// return zero oob bytes
		t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
	}
	oob2 = oob2[:oobn2]
	if !bytes.Equal(oob, oob2) {
		t.Fatal("ReadMsgUnix oob bytes don't match")
	}

	scm, err := syscall.ParseSocketControlMessage(oob2)
	if err != nil {
		t.Fatalf("ParseSocketControlMessage: %v", err)
	}
	newUcred, err := syscall.ParseUnixCredentials(&scm[0])
	if err != nil {
		t.Fatalf("ParseUnixCredentials: %v", err)
	}
	if *newUcred != ucred {
		t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
	}
}
Esempio n. 27
0
// TestPassFD tests passing a file descriptor over a Unix socket.
//
// This test involved both a parent and child process. The parent
// process is invoked as a normal test, with "go test", which then
// runs the child process by running the current test binary with args
// "-test.run=^TestPassFD$" and an environment variable used to signal
// that the test should become the child process instead.
func TestPassFD(t *testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
		passFDChild()
		return
	}

	tempDir, err := ioutil.TempDir("", "TestPassFD")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
	if err != nil {
		t.Fatalf("Socketpair: %v", err)
	}
	defer syscall.Close(fds[0])
	defer syscall.Close(fds[1])
	writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
	readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
	defer writeFile.Close()
	defer readFile.Close()

	cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
	cmd.ExtraFiles = []*os.File{writeFile}

	out, err := cmd.CombinedOutput()
	if len(out) > 0 || err != nil {
		t.Fatalf("child process: %q, %v", out, err)
	}

	c, err := net.FileConn(readFile)
	if err != nil {
		t.Fatalf("FileConn: %v", err)
	}
	defer c.Close()

	uc, ok := c.(*net.UnixConn)
	if !ok {
		t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
	}

	buf := make([]byte, 32) // expect 1 byte
	oob := make([]byte, 32) // expect 24 bytes
	closeUnix := time.AfterFunc(5*time.Second, func() {
		t.Logf("timeout reading from unix socket")
		uc.Close()
	})
	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
	closeUnix.Stop()

	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		t.Fatalf("ParseSocketControlMessage: %v", err)
	}
	if len(scms) != 1 {
		t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
	}
	scm := scms[0]
	gotFds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		t.Fatalf("syscall.ParseUnixRights: %v", err)
	}
	if len(gotFds) != 1 {
		t.Fatalf("wanted 1 fd; got %#v", gotFds)
	}

	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
	defer f.Close()

	got, err := ioutil.ReadAll(f)
	want := "Hello from child process!\n"
	if string(got) != want {
		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
	}
}
Esempio n. 28
0
func mount(dir string, conf *mountConfig, ready chan<- struct{}, errp *error) (fusefd *os.File, err error) {
	// linux mount is never delayed
	close(ready)

	fds, err := syscall.Socketpair(syscall.AF_FILE, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, fmt.Errorf("socketpair error: %v", err)
	}

	writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
	defer writeFile.Close()

	readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads")
	defer readFile.Close()

	cmd := exec.Command(
		"fusermount",
		"-o", conf.getOptions(),
		"--",
		dir,
	)
	cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")

	cmd.ExtraFiles = []*os.File{writeFile}

	var wg sync.WaitGroup
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, fmt.Errorf("setting up fusermount stderr: %v", err)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return nil, fmt.Errorf("setting up fusermount stderr: %v", err)
	}

	if err := cmd.Start(); err != nil {
		return nil, fmt.Errorf("fusermount: %v", err)
	}
	helperErrCh := make(chan error, 1)
	wg.Add(2)
	go lineLogger(&wg, "mount helper output", neverIgnoreLine, stdout)
	go lineLogger(&wg, "mount helper error", handleFusermountStderr(helperErrCh), stderr)
	wg.Wait()
	if err := cmd.Wait(); err != nil {
		// see if we have a better error to report
		select {
		case helperErr := <-helperErrCh:
			// log the Wait error if it's not what we expected
			if !isBoringFusermountError(err) {
				log.Printf("mount helper failed: %v", err)
			}
			// and now return what we grabbed from stderr as the real
			// error
			return nil, helperErr
		default:
			// nope, fall back to generic message
		}

		return nil, fmt.Errorf("fusermount: %v", err)
	}

	c, err := net.FileConn(readFile)
	if err != nil {
		return nil, fmt.Errorf("FileConn from fusermount socket: %v", err)
	}
	defer c.Close()

	uc, ok := c.(*net.UnixConn)
	if !ok {
		return nil, fmt.Errorf("unexpected FileConn type; expected UnixConn, got %T", c)
	}

	buf := make([]byte, 32) // expect 1 byte
	oob := make([]byte, 32) // expect 24 bytes
	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
	if err != nil {
		return nil, fmt.Errorf("ParseSocketControlMessage: %v", err)
	}
	if len(scms) != 1 {
		return nil, fmt.Errorf("expected 1 SocketControlMessage; got scms = %#v", scms)
	}
	scm := scms[0]
	gotFds, err := syscall.ParseUnixRights(&scm)
	if err != nil {
		return nil, fmt.Errorf("syscall.ParseUnixRights: %v", err)
	}
	if len(gotFds) != 1 {
		return nil, fmt.Errorf("wanted 1 fd; got %#v", gotFds)
	}
	f := os.NewFile(uintptr(gotFds[0]), "/dev/fuse")
	return f, nil
}
Esempio n. 29
0
func (t *unixTransport) ReadMessage() (*Message, error) {
	var (
		blen, hlen uint32
		csheader   [16]byte
		headers    []header
		order      binary.ByteOrder
		unixfds    uint32
	)
	// To be sure that all bytes of out-of-band data are read, we use a special
	// reader that uses ReadUnix on the underlying connection instead of Read
	// and gathers the out-of-band data in a buffer.
	rd := &oobReader{conn: t.UnixConn}
	// read the first 16 bytes (the part of the header that has a constant size),
	// from which we can figure out the length of the rest of the message
	if _, err := io.ReadFull(rd, csheader[:]); err != nil {
		return nil, err
	}
	switch csheader[0] {
	case 'l':
		order = binary.LittleEndian
	case 'B':
		order = binary.BigEndian
	default:
		return nil, InvalidMessageError("invalid byte order")
	}
	// csheader[4:8] -> length of message body, csheader[12:16] -> length of
	// header fields (without alignment)
	binary.Read(bytes.NewBuffer(csheader[4:8]), order, &blen)
	binary.Read(bytes.NewBuffer(csheader[12:]), order, &hlen)
	if hlen%8 != 0 {
		hlen += 8 - (hlen % 8)
	}

	// decode headers and look for unix fds
	headerdata := make([]byte, hlen+4)
	copy(headerdata, csheader[12:])
	if _, err := io.ReadFull(t, headerdata[4:]); err != nil {
		return nil, err
	}
	dec := newDecoder(bytes.NewBuffer(headerdata), order)
	dec.pos = 12
	vs, err := dec.Decode(Signature{"a(yv)"})
	if err != nil {
		return nil, err
	}
	Store(vs, &headers)
	for _, v := range headers {
		if v.Field == byte(FieldUnixFDs) {
			unixfds, _ = v.Variant.value.(uint32)
		}
	}
	all := make([]byte, 16+hlen+blen)
	copy(all, csheader[:])
	copy(all[16:], headerdata[4:])
	if _, err := io.ReadFull(rd, all[16+hlen:]); err != nil {
		return nil, err
	}
	if unixfds != 0 {
		if !t.hasUnixFDs {
			return nil, errors.New("dbus: got unix fds on unsupported transport")
		}
		// read the fds from the OOB data
		scms, err := syscall.ParseSocketControlMessage(rd.oob)
		if err != nil {
			return nil, err
		}
		if len(scms) != 1 {
			return nil, errors.New("dbus: received more than one socket control message")
		}
		fds, err := syscall.ParseUnixRights(&scms[0])
		if err != nil {
			return nil, err
		}
		msg, err := DecodeMessage(bytes.NewBuffer(all))
		if err != nil {
			return nil, err
		}
		// substitute the values in the message body (which are indices for the
		// array receiver via OOB) with the actual values
		for i, v := range msg.Body {
			if j, ok := v.(UnixFDIndex); ok {
				if uint32(j) >= unixfds {
					return nil, InvalidMessageError("invalid index for unix fd")
				}
				msg.Body[i] = UnixFD(fds[j])
			}
		}
		return msg, nil
	}
	return DecodeMessage(bytes.NewBuffer(all))
}
Esempio n. 30
0
// Up activates packet processing.
// When the interface is down(IFF_UP is unset), opening the socket raise error.
// This is because we have to call Up each time the state changed.
func (self *NamedPort) Up() error {
	self.lock.Lock()
	defer self.lock.Unlock()
	if self.fd != -1 {
		return nil // already up
	}
	if self.flags&syscall.IFF_UP == 0 {
		return nil // not ready for up
	}
	if fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, 0); err != nil {
		panic(err)
	} else {
		self.fd = fd
	}
	if err := func() error {
		if err := syscall.SetsockoptInt(self.fd, syscall.SOL_PACKET, syscall2.PACKET_AUXDATA, 1); err != nil {
			return err
		}
		if err := syscall.Bind(self.fd, &syscall.SockaddrLinklayer{
			Protocol: syscall2.ETH_P_ALL,
			Ifindex:  int(self.ifIndex),
		}); err != nil {
			return err
		}
		if sa, err := syscall.Getsockname(self.fd); err != nil {
			return err
		} else {
			self.hatype = sa.(*syscall.SockaddrLinklayer).Hatype
			switch self.hatype {
			default:
				panic("unsupported ARPHRD")
			case syscall.ARPHRD_IEEE80211_RADIOTAP:
				// ok
			case syscall.ARPHRD_ETHER:
				// ok
			case syscall2.ARPHRD_6LOWPAN:
				// ok
			}
		}
		return nil
	}(); err != nil {
		self.Down()
		return err
	}
	go func() {
		defer self.Down()
		buf := make([]byte, 32*1024)               // enough for jumbo frame
		oob := make([]byte, syscall.CmsgSpace(20)) // msg_control, 20 = sizeof(auxdata)
		for {
			var frame Frame

			if bufN, oobN, flags, _, err := syscall.Recvmsg(self.fd, buf, oob, syscall.MSG_TRUNC); err != nil {
				if e, ok := err.(syscall.Errno); ok && e.Temporary() {
					continue
				} else {
					log.Print("Recvmsg", err)
					break
				}
			} else if bufN == 0 {
				break
			} else if bufN > len(buf) {
				log.Print("MSG_TRUNC")
			} else if flags&syscall.MSG_CTRUNC != 0 {
				log.Print("MSG_CTRUNC")
			} else {
				haveVlan := false
				var vlanTpid uint16 = 0x8100
				var vlanTci uint16
				if cmsgs, err := syscall.ParseSocketControlMessage(oob[:oobN]); err != nil {
					log.Print(err)
					return
				} else {
					for _, cmsg := range cmsgs {
						switch cmsg.Header.Type {
						case syscall2.PACKET_AUXDATA:
							aux := (*syscall2.Auxdata)(unsafe.Pointer(&cmsg.Data[0]))
							switch len(cmsg.Data) {
							case 20:
								if aux.Status&syscall2.TP_STATUS_VLAN_TPID_VALID != 0 {
									vlanTpid = aux.VlanTpid
								}
							case 18:
								// old format. pass
							default:
								log.Print("unexpected PACKET_AUXDATA")
								return
							}
							if aux.Status&syscall2.TP_STATUS_VLAN_VALID != 0 {
								haveVlan = true
								vlanTci = aux.VlanTci
							}
						}
					}
				}
				switch self.hatype {
				case syscall.ARPHRD_ETHER:
					var pkt []byte
					if haveVlan {
						pkt = make([]byte, bufN+4)
						copy(pkt[:12], buf[:12])
						binary.BigEndian.PutUint16(pkt[12:], vlanTpid)
						binary.BigEndian.PutUint16(pkt[14:], vlanTci)
						copy(pkt[16:], buf[12:bufN])
					} else {
						pkt = make([]byte, bufN)
						copy(pkt, buf)
					}
					frame = Frame{
						Data: pkt,
					}
				case syscall.ARPHRD_IEEE80211_RADIOTAP:
					// NOTE: 802.11 + PACKET_AUXDATA unsupported
					bpkt := gopacket.NewPacket(buf[:bufN], layers.LayerTypeRadioTap, gopacket.Lazy)
					if rtl := bpkt.Layer(layers.LayerTypeRadioTap); rtl == nil {
						log.Print("radiotap layer error")
					} else if rt, ok := rtl.(*layers.RadioTap); !ok {
						log.Print("radiotap layer type error")
					} else {
						if f, err := FrameFromRadiotap(rt); err != nil {
							log.Print(err)
						} else {
							frame = f
						}
					}
				case syscall2.ARPHRD_6LOWPAN:
					pkt := make([]byte, 14+bufN)
					binary.BigEndian.PutUint16(pkt[12:], 0x86DD)
					copy(pkt[14:], buf[:bufN])

					bpkt := gopacket.NewPacket(buf[:bufN], layers.LayerTypeIPv6, gopacket.Lazy)
					ip6 := bpkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
					if ip6.DstIP.IsMulticast() {
						copy(pkt, []byte{0x33, 0x33})
						copy(pkt[2:6], []byte(ip6.DstIP.To16())[12:16])
						copy(pkt[6:], self.get6lowpanMac(ip6.SrcIP))
					} else {
						copy(pkt[6:], self.get6lowpanMac(ip6.SrcIP))
						copy(pkt, self.get6lowpanMac(ip6.DstIP))
					}
					frame = Frame{
						Data: pkt,
					}
				}
				if len(frame.Data) != 0 {
					func() {
						defer func() {
							if r := recover(); r != nil {
								// this may happen in socket race condition(rtnetlink and pf_packet).
								fmt.Println("dropping packet on closed ingress.")
							}
						}()
						self.ingress <- frame
					}()
				}
			}
		}
	}()
	return nil
}