func createTty(p *libcontainer.Process, rootuid int, consolePath string) (*tty, error) { if consolePath != "" { if err := p.ConsoleFromPath(consolePath); err != nil { return nil, err } return &tty{}, nil } console, err := p.NewConsole(rootuid) if err != nil { return nil, err } go io.Copy(console, os.Stdin) go io.Copy(os.Stdout, console) state, err := term.SetRawTerminal(os.Stdin.Fd()) if err != nil { return nil, fmt.Errorf("failed to set the terminal from the stdin: %v", err) } t := &tty{ console: console, state: state, closers: []io.Closer{ console, }, } return t, nil }
func createTty(p *libcontainer.Process, rootuid int) (*tty, error) { console, err := p.NewConsole(rootuid) if err != nil { return nil, err } go io.Copy(console, os.Stdin) go io.Copy(os.Stdout, console) state, err := term.SetRawTerminal(os.Stdin.Fd()) if err != nil { return nil, err } t := &tty{ console: console, state: state, closers: []io.Closer{ console, }, } p.Stderr = nil p.Stdout = nil p.Stdin = nil return t, nil }
func setupPipes(container *configs.Config, processConfig *execdriver.ProcessConfig, p *libcontainer.Process, pipes *execdriver.Pipes) error { var term execdriver.Terminal var err error if processConfig.Tty { rootuid, err := container.HostUID() if err != nil { return err } cons, err := p.NewConsole(rootuid) if err != nil { return err } term, err = NewTtyConsole(cons, pipes) } else { p.Stdout = pipes.Stdout p.Stderr = pipes.Stderr r, w, err := os.Pipe() if err != nil { return err } if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } term = &execdriver.StdConsole{} } if err != nil { return err } processConfig.Terminal = term return nil }
func setupPipes(container *configs.Config, processConfig *execdriver.ProcessConfig, p *libcontainer.Process, pipes *execdriver.Pipes) error { rootuid, err := container.HostUID() if err != nil { return err } if processConfig.Tty { cons, err := p.NewConsole(rootuid) if err != nil { return err } term, err := NewTtyConsole(cons, pipes) if err != nil { return err } processConfig.Terminal = term return nil } // not a tty--set up stdio pipes term := &execdriver.StdConsole{} processConfig.Terminal = term // if we are not in a user namespace, there is no reason to go through // the hassle of setting up os-level pipes with proper (remapped) ownership // so we will do the prior shortcut for non-userns containers if rootuid == 0 { p.Stdout = pipes.Stdout p.Stderr = pipes.Stderr r, w, err := os.Pipe() if err != nil { return err } if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } return nil } // if we have user namespaces enabled (rootuid != 0), we will set // up os pipes for stderr, stdout, stdin so we can chown them to // the proper ownership to allow for proper access to the underlying // fds var fds []int //setup stdout r, w, err := os.Pipe() if err != nil { return err } fds = append(fds, int(r.Fd()), int(w.Fd())) if pipes.Stdout != nil { go io.Copy(pipes.Stdout, r) } term.Closers = append(term.Closers, r) p.Stdout = w //setup stderr r, w, err = os.Pipe() if err != nil { return err } fds = append(fds, int(r.Fd()), int(w.Fd())) if pipes.Stderr != nil { go io.Copy(pipes.Stderr, r) } term.Closers = append(term.Closers, r) p.Stderr = w //setup stdin r, w, err = os.Pipe() if err != nil { return err } fds = append(fds, int(r.Fd()), int(w.Fd())) if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } for _, fd := range fds { if err := syscall.Fchown(fd, rootuid, rootuid); err != nil { return fmt.Errorf("Failed to chown pipes fd: %v", err) } } return nil }
func setupPipes(container *configs.Config, processConfig *execdriver.ProcessConfig, p *libcontainer.Process, pipes *execdriver.Pipes, wg *sync.WaitGroup) ([]io.WriteCloser, error) { writers := []io.WriteCloser{} rootuid, err := container.HostUID() if err != nil { return writers, err } if processConfig.Tty { cons, err := p.NewConsole(rootuid) if err != nil { return writers, err } term, err := NewTtyConsole(cons, pipes) if err != nil { return writers, err } processConfig.Terminal = term return writers, nil } // not a tty--set up stdio pipes term := &execdriver.StdConsole{} processConfig.Terminal = term // if we are not in a user namespace, there is no reason to go through // the hassle of setting up os-level pipes with proper (remapped) ownership // so we will do the prior shortcut for non-userns containers if rootuid == 0 { p.Stdout = pipes.Stdout p.Stderr = pipes.Stderr r, w, err := os.Pipe() if err != nil { return writers, err } if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } return writers, nil } // if we have user namespaces enabled (rootuid != 0), we will set // up os pipes for stderr, stdout, stdin so we can chown them to // the proper ownership to allow for proper access to the underlying // fds var fds []uintptr copyPipes := func(out io.Writer, in io.ReadCloser) { defer wg.Done() io.Copy(out, in) in.Close() } //setup stdout r, w, err := os.Pipe() if err != nil { w.Close() return writers, err } writers = append(writers, w) fds = append(fds, r.Fd(), w.Fd()) if pipes.Stdout != nil { wg.Add(1) go copyPipes(pipes.Stdout, r) } term.Closers = append(term.Closers, r) p.Stdout = w //setup stderr r, w, err = os.Pipe() if err != nil { w.Close() return writers, err } writers = append(writers, w) fds = append(fds, r.Fd(), w.Fd()) if pipes.Stderr != nil { wg.Add(1) go copyPipes(pipes.Stderr, r) } term.Closers = append(term.Closers, r) p.Stderr = w //setup stdin r, w, err = os.Pipe() if err != nil { r.Close() return writers, err } fds = append(fds, r.Fd(), w.Fd()) if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } for _, fd := range fds { if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil { return writers, fmt.Errorf("Failed to chown pipes fd: %v", err) } } return writers, nil }