libcontainer: Don't use UsetCloseOnExec, it is racy

We can't keep file descriptors without close-on-exec except with
syscall.ForkLock held, as otherwise they could leak by accident into
other children from forks in other threads.

Instead we just use Cmd.ExtraFiles which handles all this for us.

This fixes https://github.com/dotcloud/docker/issues/4493

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
Upstream-commit: 5c9b28db1853cccdf7a1037eeaad372d12cd68fa
Component: engine
This commit is contained in:
Alexander Larsson
2014-03-06 14:10:32 +01:00
parent 2eb4a2724e
commit 098ea0f413
4 changed files with 8 additions and 9 deletions
@@ -239,7 +239,7 @@ type dockerCommandFactory struct {
// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (d *dockerCommandFactory) Create(container *libcontainer.Container, console string, syncFd uintptr, args []string) *exec.Cmd {
func (d *dockerCommandFactory) Create(container *libcontainer.Container, console string, syncFile *os.File, args []string) *exec.Cmd {
// we need to join the rootfs because nsinit will setup the rootfs and chroot
initPath := filepath.Join(d.c.Rootfs, d.c.InitPath)
@@ -248,7 +248,7 @@ func (d *dockerCommandFactory) Create(container *libcontainer.Container, console
initPath,
"-driver", DriverName,
"-console", console,
"-pipe", fmt.Sprint(syncFd),
"-pipe", "3",
"-root", filepath.Join(d.driver.root, d.c.ID),
"--",
}, args...)
@@ -256,6 +256,7 @@ func (d *dockerCommandFactory) Create(container *libcontainer.Container, console
// set this to nil so that when we set the clone flags anything else is reset
d.c.SysProcAttr = nil
system.SetCloneFlags(&d.c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces)))
d.c.ExtraFiles = []*os.File{syncFile}
d.c.Env = container.Env
d.c.Dir = d.c.Rootfs
@@ -1,7 +1,6 @@
package nsinit
import (
"fmt"
"github.com/dotcloud/docker/pkg/libcontainer"
"github.com/dotcloud/docker/pkg/system"
"os"
@@ -12,7 +11,7 @@ import (
// parent processes and creates an *exec.Cmd that will be used to fork/exec the
// namespaced init process
type CommandFactory interface {
Create(container *libcontainer.Container, console string, syncFd uintptr, args []string) *exec.Cmd
Create(container *libcontainer.Container, console string, syncFd *os.File, args []string) *exec.Cmd
}
type DefaultCommandFactory struct {
@@ -22,16 +21,17 @@ type DefaultCommandFactory struct {
// Create will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided
func (c *DefaultCommandFactory) Create(container *libcontainer.Container, console string, pipe uintptr, args []string) *exec.Cmd {
func (c *DefaultCommandFactory) Create(container *libcontainer.Container, console string, pipe *os.File, args []string) *exec.Cmd {
// get our binary name from arg0 so we can always reexec ourself
command := exec.Command(os.Args[0], append([]string{
"-console", console,
"-pipe", fmt.Sprint(pipe),
"-pipe", "3",
"-root", c.Root,
"init"}, args...)...)
system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces)))
command.Env = container.Env
command.ExtraFiles = []*os.File{pipe}
return command
}
@@ -35,7 +35,7 @@ func (ns *linuxNs) Exec(container *libcontainer.Container, term Terminal, args [
term.SetMaster(master)
}
command := ns.commandFactory.Create(container, console, syncPipe.child.Fd(), args)
command := ns.commandFactory.Create(container, console, syncPipe.child, args)
if err := term.Attach(command); err != nil {
return -1, err
}
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"github.com/dotcloud/docker/pkg/libcontainer"
"github.com/dotcloud/docker/pkg/system"
"io/ioutil"
"os"
)
@@ -22,7 +21,6 @@ func NewSyncPipe() (s *SyncPipe, err error) {
if err != nil {
return nil, err
}
system.UsetCloseOnExec(s.child.Fd())
return s, nil
}