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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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") }
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 }
// 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 }
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 }
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 }
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 }
// 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 }
// 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 }
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 }
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 }
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 }
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 }
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) }
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) }
// 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) } }
// 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) } }
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 }
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 }
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]) } }
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 }