Beispiel #1
0
func createAttachment(stream *spdystream.Stream) (*os.File, error) {
	if stream.IsFinished() {
		return nil, fmt.Errorf("stream already finished")
	}

	socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0)
	if socketErr != nil {
		return nil, socketErr
	}
	pipe := os.NewFile(uintptr(socketFds[1]), "")
	defer pipe.Close()
	conn, connErr := net.FileConn(pipe)
	if connErr != nil {
		return nil, connErr
	}

	go func() {
		io.Copy(conn, stream)
		conn.Close()
	}()
	go func() {
		io.Copy(stream, conn)
	}()

	return os.NewFile(uintptr(socketFds[0]), ""), nil
}
Beispiel #2
0
func newFakeVTYServer() (*fakeVTYServer, error) {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, err
	}

	vtyClientFile := os.NewFile(uintptr(fds[1]), "vty-client")
	vtyClientConn, err := net.FileConn(vtyClientFile)
	if err != nil {
		return nil, err
	}

	vtyServerFile := os.NewFile(uintptr(fds[0]), "vty-server")
	vtyServerConn, err := net.FileConn(vtyServerFile)
	if err != nil {
		return nil, err
	}
	syscall.SetNonblock(fds[0], false)

	vs := &fakeVTYServer{
		clientConn: vtyClientConn,
		serverConn: vtyServerConn,
		clientFile: vtyClientFile,
		serverFile: vtyServerFile,

		send:     make(chan []byte),
		received: make(chan []byte),
	}

	go vs.read()
	go vs.write()

	return vs, nil
}
Beispiel #3
0
func newPipe() (parent *os.File, child *os.File, err error) {
	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return nil, nil, err
	}
	return os.NewFile(uintptr(fds[1]), "parent"), os.NewFile(uintptr(fds[0]), "child"), nil
}
Beispiel #4
0
func newSocketPair(name string) (*os.File, *os.File, error) {
	pair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, nil, err
	}
	return os.NewFile(uintptr(pair[0]), name), os.NewFile(uintptr(pair[1]), name), nil
}
Beispiel #5
0
func socketPair() (sock1 *os.File, sock2 *os.File, err error) {
	var fds [2]int
	fds, err = syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
	if err != nil {
		fmt.Println(err.Error())
	}
	return os.NewFile(uintptr(fds[0]), "|0"), os.NewFile(uintptr(fds[1]), "|1"), err
}
Beispiel #6
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
}
Beispiel #7
0
func newCtlSockets() (*os.File, *os.File, error) {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
	if err != nil {
		return nil, nil, err
	}

	f1 := os.NewFile(uintptr(fds[0]), "ctl")
	f2 := os.NewFile(uintptr(fds[1]), "ctl")
	return f1, f2, nil
}
Beispiel #8
0
func (k *PosixKernel) Socketpair(domain, typ, proto int, vector co.Obuf) uint64 {
	pair, err := syscall.Socketpair(domain, typ, proto)
	if err != nil {
		return Errno(err)
	}
	if err := vector.Pack(pair); err != nil {
		return UINT64_MAX // FIXME
	}
	return 0
}
Beispiel #9
0
func unixgramSocketpair() (l, r *os.File, err error) {
	fd, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
	if err != nil {
		return nil, nil, os.NewSyscallError("socketpair",
			err.(syscall.Errno))
	}
	l = os.NewFile(uintptr(fd[0]), "socketpair-half1")
	r = os.NewFile(uintptr(fd[1]), "socketpair-half2")
	return
}
Beispiel #10
0
func (sp *SocketPair) init() {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)

	if err != nil {
		fmt.Println(err)
		return
	}
	sp.LocalFile = os.NewFile(uintptr(fds[0]), "sp-0")
	sp.RemoteFile = os.NewFile(uintptr(fds[1]), "sp-1")

}
Beispiel #11
0
func Socketpair(typ int) (a, b *os.File, err error) {
	fd, err := syscall.Socketpair(syscall.AF_UNIX, typ, 0)
	if err != nil {
		e := os.NewSyscallError("socketpair", err.(syscall.Errno))
		return nil, nil, e
	}

	a = FdToFile(fd[0], "socketpair-a")
	b = FdToFile(fd[1], "socketpair-b")
	return
}
Beispiel #12
0
// Gets a channel on which to publish events.
//
// Returns a file on which the process is supposed to write data, which then
// translate into these events.
func startProcessNotifier(ready chan<- bool) (w *os.File, err error) {
	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_DGRAM, 0)
	if err != nil {
		return
	}
	r := os.NewFile(uintptr(fds[0]), "notify:r") // File name is arbitrary
	w = os.NewFile(uintptr(fds[1]), "notify:w")

	go runProcessNotifier(r, ready)

	return w, nil
}
Beispiel #13
0
func NewSyncPipe() (s *SyncPipe, err error) {
	s = &SyncPipe{}

	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return nil, err
	}

	s.child = os.NewFile(uintptr(fds[0]), "child syncpipe")
	s.parent = os.NewFile(uintptr(fds[1]), "parent syncpipe")

	return s, nil
}
Beispiel #14
0
func createStreamMessage(stream *spdystream.Stream, mode int, streamChans streamChanProvider, ret libchan.Sender) (*libchan.Message, error) {
	dataString := stream.Headers()["Data"]
	if len(dataString) != 1 {
		if len(dataString) == 0 {
			return nil, fmt.Errorf("Stream(%s) is missing data header", stream)
		} else {
			return nil, fmt.Errorf("Stream(%s) has multiple data headers", stream)
		}
	}

	data, decodeErr := base64.URLEncoding.DecodeString(dataString[0])
	if decodeErr != nil {
		return nil, decodeErr
	}

	var attach *os.File
	if !stream.IsFinished() {
		socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0)
		if socketErr != nil {
			return nil, socketErr
		}
		attach = os.NewFile(uintptr(socketFds[0]), "")
		conn, connErr := net.FileConn(os.NewFile(uintptr(socketFds[1]), ""))
		if connErr != nil {
			return nil, connErr
		}

		go func() {
			io.Copy(conn, stream)
		}()
		go func() {
			io.Copy(stream, conn)
		}()
	}

	retSender := ret
	if retSender == nil || libchan.RetPipe.Equals(retSender) {
		retSender = &StreamSender{stream: stream, streamChans: streamChans}
	}

	if mode&libchan.Ret == 0 {
		retSender.Close()
	}

	return &libchan.Message{
		Data: data,
		Fd:   attach,
		Ret:  retSender,
	}, nil
}
Beispiel #15
0
func (e *Executor) run() {
	stackState := e.runner.prog.getStack()
	stackOffset := len(e.runner.stack) - len(stackState)
	copy(e.runner.stack[stackOffset:], stackState)

	resumeResult := 0 // don't resume
	if len(stackState) > 0 {
		resumeResult = -1 // resume; return this value to snapshot function caller
	}

	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return
	}

	done := make(chan struct{})

	defer func() {
		syscall.Close(fds[1])
		<-done
	}()

	go func() {
		defer close(done)
		e.slave(fds[0], e.sigs, e.printer, e.cont)
	}()

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	setRunArg(e.arg)

	globalsMemoryAddr := (*reflect.SliceHeader)(unsafe.Pointer(&e.runner.globalsMemory)).Data
	memoryAddr := globalsMemoryAddr + uintptr(e.runner.memoryOffset)
	growMemorySize := len(e.runner.globalsMemory) - e.runner.memoryOffset

	trap, memorySize, stackPtr := run(e.runner.prog.getText(), int(e.runner.memorySize), memoryAddr, uintptr(growMemorySize), e.runner.stack, stackOffset, resumeResult, fds[1])

	e.runner.memorySize = wasm.MemorySize(memorySize)
	e.runner.lastTrap = traps.Id(trap)
	e.runner.lastStackPtr = stackPtr

	if trap == 0 {
		e.result = getRunResult()
	} else {
		e.err = e.runner.lastTrap
	}
	return
}
Beispiel #16
0
// connect the network block device
func (nbd *NBD) Connect() (dev string, err error) {
	pair, err := syscall.Socketpair(syscall.SOCK_STREAM, syscall.AF_UNIX, 0)

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

	// find free nbd device
	for i := 0; ; i++ {
		dev = fmt.Sprintf("/dev/nbd%d", i)
		if _, err = os.Stat(dev); os.IsNotExist(err) {
			dev = ""
			break // no more devices
		}
		if _, err = os.Stat(fmt.Sprintf("/sys/block/nbd%d/pid", i)); !os.IsNotExist(err) {
			continue // busy
		}

		if nbd.nbd, err = os.Open(dev); err == nil {
			// possible candidate
			ioctl(nbd.nbd.Fd(), BLKROSET, 0) // I'm really sorry about this
			if err := ioctl(nbd.nbd.Fd(), NBD_SET_SOCK, uintptr(pair[0])); err == nil {
				nbd.socket = pair[1]
				break // success
			}
		}
	}

	// setup
	if err = nbd.Size(nbd.size); err != nil {
		// already set by nbd.Size()
	} else if err = ioctl(nbd.nbd.Fd(), NBD_SET_FLAGS, 1); err != nil {
		err = &os.PathError{nbd.nbd.Name(), "ioctl NBD_SET_FLAGS", err}
	} else {
		c := make(chan error)
		go nbd.do_it(c)
		for {
			select {
			case err = <-c:
				return dev, err
			default:
				nbd.handle()
			}
		}
	}

	return dev, err
}
Beispiel #17
0
// Connect the network block device.
func (nbd *NBD) Connect() (dev string, err error) {
	pair, err := syscall.Socketpair(syscall.SOCK_STREAM, syscall.AF_UNIX, 0)
	if err != nil {
		return "", err
	}

	// Find free NBD device.
	for i := 0; ; i++ {
		dev = fmt.Sprintf("/dev/nbd%d", i)
		if _, err = os.Stat(dev); os.IsNotExist(err) {
			dev = ""
			return "", errors.New("No more NBD devices left.")
		}
		if _, err = os.Stat(fmt.Sprintf("/sys/block/nbd%d/pid", i)); !os.IsNotExist(err) {
			continue // Busy.
		}

		dlog.Infof("Attempting to open device %v", dev)
		if nbd.deviceFile, err = os.Open(dev); err == nil {
			// Possible candidate.
			ioctl(nbd.deviceFile.Fd(), BLKROSET, 0)
			if err := ioctl(nbd.deviceFile.Fd(), NBD_SET_SOCK, uintptr(pair[0])); err == nil {
				nbd.socket = pair[1]
				break // Success.
			}
		}
	}

	// Setup.
	if err = nbd.Size(nbd.size); err != nil {
		// Already set by nbd.Size().
	} else if err = ioctl(nbd.deviceFile.Fd(), NBD_SET_FLAGS, 1); err != nil {
		err = &os.PathError{nbd.deviceFile.Name(), "ioctl NBD_SET_FLAGS", err}
	} else {
		go nbd.connect()
		go nbd.handle()
	}

	nbd.devicePath = dev

	return dev, err
}
Beispiel #18
0
func startChildOf(testName string) (net.Conn, *exec.Cmd, error) {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, nil, err
	}

	conn, err := fdConn(fds[0])
	if err != nil {
		return nil, nil, err
	}

	cmd := exec.Command(os.Args[0], "-test.run="+testName)
	cmd.Env = append([]string{
		fmt.Sprintf("TEST_CHILD_FD=%d", fds[1]),
	})

	err = cmd.Start()

	return conn, cmd, err
}
Beispiel #19
0
func Socketpair(network string) (l, r *os.File, err os.Error) {
	var domain int
	var typ int
	switch network {
	default:
		panic("unknown network " + network)
	case "unix":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_STREAM
	case "unixgram":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_SEQPACKET
	}
	fd, errno := syscall.Socketpair(domain, typ, 0)
	if errno != 0 {
		return nil, nil, os.NewSyscallError("socketpair", errno)
	}
	l = os.NewFile(fd[0], "socketpair-half1")
	r = os.NewFile(fd[1], "socketpair-half2")
	return
}
func (nbd *NBD) OpenDevice(dev string) (string, error) {
	f, err := os.Open(dev)
	if err != nil {
		return "", err
	}
	nbd.nbd = f

	// possible candidate
	ioctl(f.Fd(), BLKROSET, 0) // I'm really sorry about this
	pair, err := syscall.Socketpair(syscall.SOCK_STREAM, syscall.AF_UNIX, 0)
	if err != nil {
		return "", err
	}
	if err := ioctl(f.Fd(), ioctlSetSock, uintptr(pair[0])); err != nil {
		return "", err
	}

	nbd.setsocket = pair[0] // FIXME: We shouldn't hold on to this.
	nbd.socket = pair[1]
	return dev, nil
}
Beispiel #21
0
func Socketpair(network string) (l, r *os.File, err error) {
	var domain int
	var typ int
	switch network {
	case "unix":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_STREAM
	case "unixgram":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_SEQPACKET
	default:
		log.Panicf("unknown network %q", network)
	}
	fd, err := syscall.Socketpair(domain, typ, 0)
	if err != nil {
		return nil, nil, os.NewSyscallError("socketpair",
			err.(syscall.Errno))
	}
	l = os.NewFile(fd[0], "socketpair-half1")
	r = os.NewFile(fd[1], "socketpair-half2")
	return
}
Beispiel #22
0
func (h *Host) exec(cmd *host.Command, listener *os.File) (*Child, error) {
	// create a control socket for communicating with the child
	sockPair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if err != nil {
		return nil, fmt.Errorf("error creating socketpair: %s", err)
	}

	dir, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("error getting working directory: %s", err)
	}

	h.statusMtx.RLock()
	status, err := json.Marshal(h.status)
	h.statusMtx.RUnlock()
	if err != nil {
		return nil, fmt.Errorf("error marshaling status JSON: %s", err)
	}

	c := exec.Command(cmd.Path, cmd.Args...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	c.Dir = dir
	c.ExtraFiles = []*os.File{
		listener,
		os.NewFile(uintptr(sockPair[1]), "child"),
	}
	setEnv(c, map[string]string{
		"FLYNN_HTTP_FD":     "3",
		"FLYNN_CONTROL_FD":  "4",
		"FLYNN_HOST_STATUS": string(status),
	})
	if err := c.Start(); err != nil {
		return nil, fmt.Errorf("error exec'ing child: %s", err)
	}
	cmd.PID = c.Process.Pid
	syscall.Close(sockPair[1])
	return &Child{c, sockPair[0]}, nil
}
Beispiel #23
0
func main() {
	fds, errno := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if errno != 0 {
		fmt.Printf("mycat: socketpair: %v: %v\n", errno, syscall.Errstr(errno))
		os.Exit(errno)
	}
	fd0, fd1 := fds[0], fds[1]

	syscall.CloseOnExec(fd0)
	bin := "./openfile/openfile"
	argv := []string{bin, strconv.Itoa(fd1), os.Args[1]}

	pid, errno := syscall.ForkExec(bin, argv, nil)
	if errno != 0 {
		fmt.Printf("getFdFromChild: ForkExec: %v\n", syscall.Errstr(errno))
		os.Exit(1)
	}

	syscall.Close(fd1)
	getFdFromChild(pid, fd0)
	syscall.Close(fd0)
}
Beispiel #24
0
func unixPair(typ int) (*net.UnixConn, *net.UnixConn) {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, typ, 0)
	if err != nil {
		panic(os.NewSyscallError("socketpair", err))
	}
	file := os.NewFile(uintptr(fds[0]), "")
	c0, err := net.FileConn(file)
	if err != nil {
		panic(err)
	}
	if err := file.Close(); err != nil {
		panic(err)
	}
	file = os.NewFile(uintptr(fds[1]), "")
	c1, err := net.FileConn(file)
	if err != nil {
		panic(err)
	}
	if err := file.Close(); err != nil {
		panic(err)
	}
	return c0.(*net.UnixConn), c1.(*net.UnixConn)
}
Beispiel #25
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)
	}
}
Beispiel #26
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)
	}
}
Beispiel #27
0
func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool) error {
	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0)
	if err != nil {
		return err
	}

	logPath := filepath.Join(opts.WorkDirectory, req.GetOpts().GetLogFile())
	criuClient := os.NewFile(uintptr(fds[0]), "criu-transport-client")
	criuServer := os.NewFile(uintptr(fds[1]), "criu-transport-server")
	defer criuClient.Close()
	defer criuServer.Close()

	args := []string{"swrk", "3"}
	cmd := exec.Command(c.criuPath, args...)
	if process != nil {
		cmd.Stdin = process.Stdin
		cmd.Stdout = process.Stdout
		cmd.Stderr = process.Stderr
	}
	cmd.ExtraFiles = append(cmd.ExtraFiles, criuServer)

	if err := cmd.Start(); err != nil {
		return err
	}
	criuServer.Close()

	defer func() {
		criuClient.Close()
		_, err := cmd.Process.Wait()
		if err != nil {
			return
		}
	}()

	if applyCgroups {
		err := c.criuApplyCgroups(cmd.Process.Pid, req)
		if err != nil {
			return err
		}
	}

	var extFds []string
	if process != nil {
		extFds, err = getPipeFds(cmd.Process.Pid)
		if err != nil {
			return err
		}
	}

	data, err := proto.Marshal(req)
	if err != nil {
		return err
	}
	_, err = criuClient.Write(data)
	if err != nil {
		return err
	}

	buf := make([]byte, 10*4096)
	for true {
		n, err := criuClient.Read(buf)
		if err != nil {
			return err
		}
		if n == 0 {
			return fmt.Errorf("unexpected EOF")
		}
		if n == len(buf) {
			return fmt.Errorf("buffer is too small")
		}

		resp := new(criurpc.CriuResp)
		err = proto.Unmarshal(buf[:n], resp)
		if err != nil {
			return err
		}
		if !resp.GetSuccess() {
			typeString := req.GetType().String()
			return fmt.Errorf("criu failed: type %s errno %d\nlog file: %s", typeString, resp.GetCrErrno(), logPath)
		}

		t := resp.GetType()
		switch {
		case t == criurpc.CriuReqType_NOTIFY:
			if err := c.criuNotifications(resp, process, opts, extFds); err != nil {
				return err
			}
			t = criurpc.CriuReqType_NOTIFY
			req = &criurpc.CriuReq{
				Type:          &t,
				NotifySuccess: proto.Bool(true),
			}
			data, err = proto.Marshal(req)
			if err != nil {
				return err
			}
			n, err = criuClient.Write(data)
			if err != nil {
				return err
			}
			continue
		case t == criurpc.CriuReqType_RESTORE:
		case t == criurpc.CriuReqType_DUMP:
			break
		default:
			return fmt.Errorf("unable to parse the response %s", resp.String())
		}

		break
	}

	// cmd.Wait() waits cmd.goroutines which are used for proxying file descriptors.
	// Here we want to wait only the CRIU process.
	st, err := cmd.Process.Wait()
	if err != nil {
		return err
	}
	if !st.Success() {
		return fmt.Errorf("criu failed: %s\nlog file: %s", st.String(), logPath)
	}
	return nil
}
Beispiel #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
}
Beispiel #29
0
func xserverInit(display *C.struct_wl_display) {
	// Fetch a valid lock file and DISPLAY number
	displayNum, _ := TryLock()
	numStr := strconv.Itoa(displayNum)
	// Set DISPLAY number
	displayName := ":" + numStr
	os.Setenv("DISPLAY", displayName)
	println(displayName)

	// Open a socket for the Wayland connection from Xwayland.
	wls, _ := syscall.Socketpair(syscall.AF_UNIX,
		syscall.SOCK_STREAM, 0)

	wms, _ := syscall.Socketpair(syscall.AF_UNIX,
		syscall.SOCK_STREAM, 0)

	initXwm((uintptr)(wms[0]))

	client := C.wl_client_create(display, (C.int)(wls[0]))

	println(client)
	unixFd := listen2(SOCKET_FMT + numStr)
	abstructFd := listen2("@" + SOCKET_FMT + numStr)

	unsetCloseOnExec(unixFd)
	unsetCloseOnExec(abstructFd)

	pid := forkXWayland()
	if pid == 0 { // child

		unix.Close(wls[0])
		unix.Close(wms[0])

		// init DISPLAY unix socket
		// do not close the listener(Close them will remove the file in filesystem).
		// unixListener, _ := listen(SOCKET_FMT + numStr)
		// abstructListener, _ := listen("@" + SOCKET_FMT + numStr)

		// unixFile, _ := unixListener.File()
		// abstructFile, _ := abstructListener.File()

		// unixFd := unixFile.Fd()
		// abstructFd := abstructFile.Fd()

		C.signal_ignore((C.int)(syscall.SIGUSR1))
		os.Setenv("WAYLAND_SOCKET", strconv.Itoa(wls[1]))
		args := []string{
			"Xwayland",
			displayName,
			"-rootless",
			"-terminate",
			"-listen", strconv.Itoa((int)(unixFd)),
			"-listen", strconv.Itoa((int)(abstructFd)),
			"-wm", strconv.Itoa(wms[1]),
		}

		binary, lookErr := exec.LookPath("Xwayland")
		// binary, lookErr := exec.LookPath("strace")
		if lookErr != nil {
			panic(lookErr)
		}

		env := os.Environ()
		execErr := syscall.Exec(binary, args, env)
		if execErr != nil {
			panic(lookErr)
		}

	} else { // parent
		unix.Close(wls[1])
		unix.Close(wms[1])
	}
}
Beispiel #30
0
func createStreamMessage(stream *spdystream.Stream, mode int, streamChans streamChanProvider, ret beam.Sender) (*beam.Message, error) {
	verbString := stream.Headers()["Verb"]
	if len(verbString) != 1 {
		if len(verbString) == 0 {
			return nil, fmt.Errorf("Stream(%s) is missing verb header", stream)
		} else {
			return nil, fmt.Errorf("Stream(%s) has multiple verb headers", stream)
		}

	}
	verb, verbOk := verbs[verbString[0]]
	if !verbOk {
		return nil, fmt.Errorf("Unknown verb: %s", verbString[0])
	}

	var args []string
	argString := stream.Headers()["Args"]
	if len(argString) > 1 {
		return nil, fmt.Errorf("Stream(%s) has multiple args headers", stream)
	}
	if len(argString) == 1 {
		var err error
		args, err = decodeArgs(argString[0])
		if err != nil {
			return nil, err
		}
	}

	var attach *os.File
	if !stream.IsFinished() {
		socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0)
		if socketErr != nil {
			return nil, socketErr
		}
		attach = os.NewFile(uintptr(socketFds[0]), "")
		conn, connErr := net.FileConn(os.NewFile(uintptr(socketFds[1]), ""))
		if connErr != nil {
			return nil, connErr
		}

		go func() {
			io.Copy(conn, stream)
		}()
		go func() {
			io.Copy(stream, conn)
		}()
	}

	retSender := ret
	if retSender == nil || beam.RetPipe.Equals(retSender) {
		retSender = &StreamSender{stream: stream, streamChans: streamChans}
	}

	if mode&beam.Ret == 0 {
		retSender.Close()
	}

	return &beam.Message{
		Verb: verb,
		Args: args,
		Att:  attach,
		Ret:  retSender,
	}, nil
}