diff --git a/libcontainer/process.go b/libcontainer/process.go index e96dc0d3..3a81484c 100644 --- a/libcontainer/process.go +++ b/libcontainer/process.go @@ -5,6 +5,7 @@ import ( "io" "math" "os" + "syscall" ) type processOperations interface { @@ -78,6 +79,54 @@ func (p Process) Signal(sig os.Signal) error { return p.ops.signal(sig) } +// IO holds the process's STDIO +type IO struct { + Stdin io.WriteCloser + Stdout io.ReadCloser + Stderr io.ReadCloser +} + +// InitializeIO creates pipes for use with the process's STDIO +// and returns the opposite side for each +func (p *Process) InitializeIO(rootuid int) (i *IO, err error) { + var fds []uintptr + i = &IO{} + // cleanup in case of an error + defer func() { + if err != nil { + for _, fd := range fds { + syscall.Close(int(fd)) + } + } + }() + // STDIN + r, w, err := os.Pipe() + if err != nil { + return nil, err + } + fds = append(fds, r.Fd(), w.Fd()) + p.Stdin, i.Stdin = r, w + // STDOUT + if r, w, err = os.Pipe(); err != nil { + return nil, err + } + fds = append(fds, r.Fd(), w.Fd()) + p.Stdout, i.Stdout = w, r + // STDERR + if r, w, err = os.Pipe(); err != nil { + return nil, err + } + fds = append(fds, r.Fd(), w.Fd()) + p.Stderr, i.Stderr = w, r + // change ownership of the pipes incase we are in a user namespace + for _, fd := range fds { + if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil { + return nil, err + } + } + return i, nil +} + // NewConsole creates new console for process and returns it func (p *Process) NewConsole(rootuid int) (Console, error) { console, err := NewConsole(rootuid, rootuid) diff --git a/restore.go b/restore.go index ea48c710..b5b20fdd 100644 --- a/restore.go +++ b/restore.go @@ -126,11 +126,7 @@ func restoreContainer(context *cli.Context, spec *specs.LinuxSpec, config *confi } } }() - process := &libcontainer.Process{ - Stdin: os.Stdin, - Stdout: os.Stdout, - Stderr: os.Stderr, - } + process := &libcontainer.Process{} tty, err := newTty(spec.Process.Terminal, process, rootuid) if err != nil { return -1, err diff --git a/start.go b/start.go index 719a79ae..c39fa017 100644 --- a/start.go +++ b/start.go @@ -110,12 +110,10 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec, rspec *specs.Li if err != nil { return -1, err } - for i := SD_LISTEN_FDS_START; i < (listenFdsInt + SD_LISTEN_FDS_START); i++ { process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), "")) } } - tty, err := newTty(spec.Process.Terminal, process, rootuid) if err != nil { return -1, err diff --git a/tty.go b/tty.go index 284ed449..ca6d8c0d 100644 --- a/tty.go +++ b/tty.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "os" - "syscall" "github.com/docker/docker/pkg/term" "github.com/opencontainers/runc/libcontainer" @@ -25,38 +24,20 @@ func newTty(create bool, p *libcontainer.Process, rootuid int) (*tty, error) { // setup standard pipes so that the TTY of the calling runc process // is not inherited by the container. func createStdioPipes(p *libcontainer.Process, rootuid int) (*tty, error) { - var ( - t = &tty{} - fds []int - ) - r, w, err := os.Pipe() + i, err := p.InitializeIO(rootuid) if err != nil { return nil, err } - fds = append(fds, int(r.Fd()), int(w.Fd())) - go io.Copy(w, os.Stdin) - t.closers = append(t.closers, w) - p.Stdin = r - if r, w, err = os.Pipe(); err != nil { - return nil, err - } - fds = append(fds, int(r.Fd()), int(w.Fd())) - go io.Copy(os.Stdout, r) - p.Stdout = w - t.closers = append(t.closers, r) - if r, w, err = os.Pipe(); err != nil { - return nil, err - } - fds = append(fds, int(r.Fd()), int(w.Fd())) - go io.Copy(os.Stderr, r) - p.Stderr = w - t.closers = append(t.closers, r) - // change the ownership of the pipe fds incase we are in a user namespace. - for _, fd := range fds { - if err := syscall.Fchown(fd, rootuid, rootuid); err != nil { - return nil, err - } + t := &tty{ + closers: []io.Closer{ + i.Stdin, + i.Stdout, + i.Stderr, + }, } + go io.Copy(i.Stdin, os.Stdin) + go io.Copy(os.Stdout, i.Stdout) + go io.Copy(os.Stderr, i.Stderr) return t, nil } @@ -78,9 +59,6 @@ func createTty(p *libcontainer.Process, rootuid int) (*tty, error) { console, }, } - p.Stderr = nil - p.Stdout = nil - p.Stdin = nil return t, nil } diff --git a/utils.go b/utils.go index 01cf47d4..baffef18 100644 --- a/utils.go +++ b/utils.go @@ -161,10 +161,7 @@ func newProcess(p specs.Process) *libcontainer.Process { Args: p.Args, Env: p.Env, // TODO: fix libcontainer's API to better support uid/gid in a typesafe way. - User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID), - Cwd: p.Cwd, - Stdin: os.Stdin, - Stdout: os.Stdout, - Stderr: os.Stderr, + User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID), + Cwd: p.Cwd, } }