diff --git a/hack/vendor.sh b/hack/vendor.sh index 93ecc8131e..f3347d374b 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -63,4 +63,4 @@ mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar clone git github.com/godbus/dbus v1 clone git github.com/coreos/go-systemd v2 -clone git github.com/docker/libcontainer fb67bb80b4205bece36ff7096ee745ab0cee7e06 +clone git github.com/docker/libcontainer be85764f109c3f0f62cd2a5c8be9af7a599798cf diff --git a/vendor/src/github.com/docker/libcontainer/Dockerfile b/vendor/src/github.com/docker/libcontainer/Dockerfile new file mode 100644 index 0000000000..73789d1ab2 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/Dockerfile @@ -0,0 +1,8 @@ +FROM crosbymichael/golang + +RUN apt-get update && apt-get install -y gcc + +ADD . /go/src/github.com/docker/libcontainer +RUN cd /go/src/github.com/docker/libcontainer && go get -d ./... && go install ./... + +CMD ["nsinit"] diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go index be1805205a..7979009c08 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go @@ -12,7 +12,7 @@ import ( "time" "github.com/docker/libcontainer/cgroups" - "github.com/dotcloud/docker/pkg/system" + "github.com/docker/libcontainer/system" ) var ( diff --git a/vendor/src/github.com/docker/libcontainer/console/console.go b/vendor/src/github.com/docker/libcontainer/console/console.go index 519b5644cd..c0d1fb0433 100644 --- a/vendor/src/github.com/docker/libcontainer/console/console.go +++ b/vendor/src/github.com/docker/libcontainer/console/console.go @@ -7,22 +7,24 @@ import ( "os" "path/filepath" "syscall" + "unsafe" "github.com/docker/libcontainer/label" - "github.com/dotcloud/docker/pkg/system" ) // Setup initializes the proper /dev/console inside the rootfs path func Setup(rootfs, consolePath, mountLabel string) error { - oldMask := system.Umask(0000) - defer system.Umask(oldMask) + oldMask := syscall.Umask(0000) + defer syscall.Umask(oldMask) if err := os.Chmod(consolePath, 0600); err != nil { return err } + if err := os.Chown(consolePath, 0, 0); err != nil { return err } + if err := label.SetFileLabel(consolePath, mountLabel); err != nil { return fmt.Errorf("set file label %s %s", consolePath, err) } @@ -33,26 +35,94 @@ func Setup(rootfs, consolePath, mountLabel string) error { if err != nil && !os.IsExist(err) { return fmt.Errorf("create %s %s", dest, err) } + if f != nil { f.Close() } - if err := system.Mount(consolePath, dest, "bind", syscall.MS_BIND, ""); err != nil { + if err := syscall.Mount(consolePath, dest, "bind", syscall.MS_BIND, ""); err != nil { return fmt.Errorf("bind %s to %s %s", consolePath, dest, err) } + return nil } func OpenAndDup(consolePath string) error { - slave, err := system.OpenTerminal(consolePath, syscall.O_RDWR) + slave, err := OpenTerminal(consolePath, syscall.O_RDWR) if err != nil { return fmt.Errorf("open terminal %s", err) } - if err := system.Dup2(slave.Fd(), 0); err != nil { + + if err := syscall.Dup2(int(slave.Fd()), 0); err != nil { return err } - if err := system.Dup2(slave.Fd(), 1); err != nil { + + if err := syscall.Dup2(int(slave.Fd()), 1); err != nil { return err } - return system.Dup2(slave.Fd(), 2) + + return syscall.Dup2(int(slave.Fd()), 2) +} + +// Unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. +// Unlockpt should be called before opening the slave side of a pseudoterminal. +func Unlockpt(f *os.File) error { + var u int + + return Ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) +} + +// Ptsname retrieves the name of the first available pts for the given master. +func Ptsname(f *os.File) (string, error) { + var n int + + if err := Ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))); err != nil { + return "", err + } + + return fmt.Sprintf("/dev/pts/%d", n), nil +} + +// CreateMasterAndConsole will open /dev/ptmx on the host and retreive the +// pts name for use as the pty slave inside the container +func CreateMasterAndConsole() (*os.File, string, error) { + master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0) + if err != nil { + return nil, "", err + } + + console, err := Ptsname(master) + if err != nil { + return nil, "", err + } + + if err := Unlockpt(master); err != nil { + return nil, "", err + } + + return master, console, nil +} + +// OpenPtmx opens /dev/ptmx, i.e. the PTY master. +func OpenPtmx() (*os.File, error) { + // O_NOCTTY and O_CLOEXEC are not present in os package so we use the syscall's one for all. + return os.OpenFile("/dev/ptmx", syscall.O_RDONLY|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0) +} + +// OpenTerminal is a clone of os.OpenFile without the O_CLOEXEC +// used to open the pty slave inside the container namespace +func OpenTerminal(name string, flag int) (*os.File, error) { + r, e := syscall.Open(name, flag, 0) + if e != nil { + return nil, &os.PathError{"open", name, e} + } + return os.NewFile(uintptr(r), name), nil +} + +func Ioctl(fd uintptr, flag, data uintptr) error { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, flag, data); err != 0 { + return err + } + + return nil } diff --git a/vendor/src/github.com/docker/libcontainer/mount/init.go b/vendor/src/github.com/docker/libcontainer/mount/init.go index 10f0738903..daec6ac865 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/init.go +++ b/vendor/src/github.com/docker/libcontainer/mount/init.go @@ -11,7 +11,6 @@ import ( "github.com/docker/libcontainer/label" "github.com/docker/libcontainer/mount/nodes" "github.com/dotcloud/docker/pkg/symlink" - "github.com/dotcloud/docker/pkg/system" ) // default mount point flags @@ -35,10 +34,10 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) if mountConfig.NoPivotRoot { flag = syscall.MS_SLAVE } - if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { + if err := syscall.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil { return fmt.Errorf("mounting / with flags %X %s", (flag | syscall.MS_REC), err) } - if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { + if err := syscall.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } if err := mountSystem(rootfs, mountConfig); err != nil { @@ -56,7 +55,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) if err := setupDevSymlinks(rootfs); err != nil { return fmt.Errorf("dev symlinks %s", err) } - if err := system.Chdir(rootfs); err != nil { + if err := syscall.Chdir(rootfs); err != nil { return fmt.Errorf("chdir into %s %s", rootfs, err) } @@ -75,7 +74,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) } } - system.Umask(0022) + syscall.Umask(0022) return nil } @@ -87,7 +86,7 @@ func mountSystem(rootfs string, mountConfig *MountConfig) error { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } - if err := system.Mount(m.source, m.path, m.device, uintptr(m.flags), m.data); err != nil { + if err := syscall.Mount(m.source, m.path, m.device, uintptr(m.flags), m.data); err != nil { return fmt.Errorf("mounting %s into %s %s", m.source, m.path, err) } } @@ -169,11 +168,11 @@ func setupBindmounts(rootfs string, mountConfig *MountConfig) error { return fmt.Errorf("Creating new bind-mount target, %s", err) } - if err := system.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil { + if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil { return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err) } if !m.Writable { - if err := system.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil { + if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil { return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err) } } @@ -183,7 +182,7 @@ func setupBindmounts(rootfs string, mountConfig *MountConfig) error { } } if m.Private { - if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil { + if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil { return fmt.Errorf("mounting %s private %s", dest, err) } } diff --git a/vendor/src/github.com/docker/libcontainer/mount/msmoveroot.go b/vendor/src/github.com/docker/libcontainer/mount/msmoveroot.go index b336c86495..94afd3a99c 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/msmoveroot.go +++ b/vendor/src/github.com/docker/libcontainer/mount/msmoveroot.go @@ -4,16 +4,17 @@ package mount import ( "fmt" - "github.com/dotcloud/docker/pkg/system" "syscall" ) func MsMoveRoot(rootfs string) error { - if err := system.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { + if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { return fmt.Errorf("mount move %s into / %s", rootfs, err) } - if err := system.Chroot("."); err != nil { + + if err := syscall.Chroot("."); err != nil { return fmt.Errorf("chroot . %s", err) } - return system.Chdir("/") + + return syscall.Chdir("/") } diff --git a/vendor/src/github.com/docker/libcontainer/mount/nodes/nodes.go b/vendor/src/github.com/docker/libcontainer/mount/nodes/nodes.go index e3420b48bd..6a984e33fe 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/nodes/nodes.go +++ b/vendor/src/github.com/docker/libcontainer/mount/nodes/nodes.go @@ -9,13 +9,12 @@ import ( "syscall" "github.com/docker/libcontainer/devices" - "github.com/dotcloud/docker/pkg/system" ) // Create the device nodes in the container. func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error { - oldMask := system.Umask(0000) - defer system.Umask(oldMask) + oldMask := syscall.Umask(0000) + defer syscall.Umask(oldMask) for _, node := range nodesToCreate { if err := CreateDeviceNode(rootfs, node); err != nil { @@ -46,7 +45,7 @@ func CreateDeviceNode(rootfs string, node *devices.Device) error { return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path) } - if err := system.Mknod(dest, uint32(fileMode), devices.Mkdev(node.MajorNumber, node.MinorNumber)); err != nil && !os.IsExist(err) { + if err := syscall.Mknod(dest, uint32(fileMode), devices.Mkdev(node.MajorNumber, node.MinorNumber)); err != nil && !os.IsExist(err) { return fmt.Errorf("mknod %s %s", node.Path, err) } return nil diff --git a/vendor/src/github.com/docker/libcontainer/mount/pivotroot.go b/vendor/src/github.com/docker/libcontainer/mount/pivotroot.go index ffd6051367..a88ed4a84c 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/pivotroot.go +++ b/vendor/src/github.com/docker/libcontainer/mount/pivotroot.go @@ -8,8 +8,6 @@ import ( "os" "path/filepath" "syscall" - - "github.com/dotcloud/docker/pkg/system" ) func PivotRoot(rootfs string) error { @@ -17,16 +15,20 @@ func PivotRoot(rootfs string) error { if err != nil { return fmt.Errorf("can't create pivot_root dir %s, error %v", pivotDir, err) } - if err := system.Pivotroot(rootfs, pivotDir); err != nil { + + if err := syscall.PivotRoot(rootfs, pivotDir); err != nil { return fmt.Errorf("pivot_root %s", err) } - if err := system.Chdir("/"); err != nil { + + if err := syscall.Chdir("/"); err != nil { return fmt.Errorf("chdir / %s", err) } + // path to pivot dir now changed, update pivotDir = filepath.Join("/", filepath.Base(pivotDir)) - if err := system.Unmount(pivotDir, syscall.MNT_DETACH); err != nil { + if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil { return fmt.Errorf("unmount pivot_root dir %s", err) } + return os.Remove(pivotDir) } diff --git a/vendor/src/github.com/docker/libcontainer/mount/ptmx.go b/vendor/src/github.com/docker/libcontainer/mount/ptmx.go index 32c025202e..c316481adf 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/ptmx.go +++ b/vendor/src/github.com/docker/libcontainer/mount/ptmx.go @@ -4,9 +4,10 @@ package mount import ( "fmt" - "github.com/docker/libcontainer/console" "os" "path/filepath" + + "github.com/docker/libcontainer/console" ) func SetupPtmx(rootfs, consolePath, mountLabel string) error { @@ -14,13 +15,16 @@ func SetupPtmx(rootfs, consolePath, mountLabel string) error { if err := os.Remove(ptmx); err != nil && !os.IsNotExist(err) { return err } + if err := os.Symlink("pts/ptmx", ptmx); err != nil { return fmt.Errorf("symlink dev ptmx %s", err) } + if consolePath != "" { if err := console.Setup(rootfs, consolePath, mountLabel); err != nil { return err } } + return nil } diff --git a/vendor/src/github.com/docker/libcontainer/mount/readonly.go b/vendor/src/github.com/docker/libcontainer/mount/readonly.go index 0658358ad6..9b4a6f704c 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/readonly.go +++ b/vendor/src/github.com/docker/libcontainer/mount/readonly.go @@ -3,10 +3,9 @@ package mount import ( - "github.com/dotcloud/docker/pkg/system" "syscall" ) func SetReadonly() error { - return system.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "") + return syscall.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "") } diff --git a/vendor/src/github.com/docker/libcontainer/mount/remount.go b/vendor/src/github.com/docker/libcontainer/mount/remount.go index 3e00509ae0..99a01209d1 100644 --- a/vendor/src/github.com/docker/libcontainer/mount/remount.go +++ b/vendor/src/github.com/docker/libcontainer/mount/remount.go @@ -2,30 +2,30 @@ package mount -import ( - "github.com/dotcloud/docker/pkg/system" - "syscall" -) +import "syscall" func RemountProc() error { - if err := system.Unmount("/proc", syscall.MNT_DETACH); err != nil { + if err := syscall.Unmount("/proc", syscall.MNT_DETACH); err != nil { return err } - if err := system.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), ""); err != nil { + + if err := syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), ""); err != nil { return err } + return nil } func RemountSys() error { - if err := system.Unmount("/sys", syscall.MNT_DETACH); err != nil { + if err := syscall.Unmount("/sys", syscall.MNT_DETACH); err != nil { if err != syscall.EINVAL { return err } } else { - if err := system.Mount("sysfs", "/sys", "sysfs", uintptr(defaultMountFlags), ""); err != nil { + if err := syscall.Mount("sysfs", "/sys", "sysfs", uintptr(defaultMountFlags), ""); err != nil { return err } } + return nil } diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/exec.go b/vendor/src/github.com/docker/libcontainer/namespaces/exec.go index 9053f632a4..6f3838fd22 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/exec.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/exec.go @@ -3,6 +3,7 @@ package namespaces import ( + "io" "os" "os/exec" "syscall" @@ -13,18 +14,16 @@ import ( "github.com/docker/libcontainer/cgroups/systemd" "github.com/docker/libcontainer/network" "github.com/docker/libcontainer/syncpipe" - "github.com/dotcloud/docker/pkg/system" + "github.com/docker/libcontainer/system" ) // TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. // Move this to libcontainer package. // Exec performs setup outside of a namespace so that a container can be // executed. Exec is a high level function for working with container namespaces. -func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { +func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Writer, console string, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { var ( - master *os.File - console string - err error + err error ) // create a pipe so that we can syncronize with the namespaced process and @@ -35,20 +34,13 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string } defer syncPipe.Close() - if container.Tty { - master, console, err = system.CreateMasterAndConsole() - if err != nil { - return -1, err - } - term.SetMaster(master) - } - command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.Child(), args) - - if err := term.Attach(command); err != nil { - return -1, err - } - defer term.Close() + // Note: these are only used in non-tty mode + // if there is a tty for the container it will be opened within the namespace and the + // fds will be duped to stdin, stdiout, and stderr + command.Stdin = stdin + command.Stdout = stdout + command.Stderr = stderr if err := command.Start(); err != nil { return -1, err @@ -110,6 +102,7 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string return -1, err } } + return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil } @@ -145,7 +138,11 @@ func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataP command.Dir = rootfs command.Env = append(os.Environ(), env...) - system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces))) + if command.SysProcAttr == nil { + command.SysProcAttr = &syscall.SysProcAttr{} + } + command.SysProcAttr.Cloneflags = uintptr(GetNamespaceFlags(container.Namespaces)) + command.SysProcAttr.Pdeathsig = syscall.SIGKILL command.ExtraFiles = []*os.File{pipe} @@ -157,11 +154,14 @@ func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataP func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) { if container.Cgroups != nil { c := container.Cgroups + if systemd.UseSystemd() { return systemd.Apply(c, nspid) } + return fs.Apply(c, nspid) } + return nil, nil } diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/execin.go b/vendor/src/github.com/docker/libcontainer/namespaces/execin.go index 3e79f4cda8..5311adf2b3 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/execin.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/execin.go @@ -9,7 +9,7 @@ import ( "github.com/docker/libcontainer" "github.com/docker/libcontainer/label" - "github.com/dotcloud/docker/pkg/system" + "github.com/docker/libcontainer/system" ) // ExecIn uses an existing pid and joins the pid's namespaces with the new command. diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/init.go b/vendor/src/github.com/docker/libcontainer/namespaces/init.go index 4674944cb7..7c917c015d 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/init.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/init.go @@ -19,8 +19,8 @@ import ( "github.com/docker/libcontainer/security/capabilities" "github.com/docker/libcontainer/security/restrict" "github.com/docker/libcontainer/syncpipe" + "github.com/docker/libcontainer/system" "github.com/docker/libcontainer/utils" - "github.com/dotcloud/docker/pkg/system" "github.com/dotcloud/docker/pkg/user" ) @@ -57,7 +57,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn return err } } - if _, err := system.Setsid(); err != nil { + if _, err := syscall.Setsid(); err != nil { return fmt.Errorf("setsid %s", err) } if consolePath != "" { @@ -81,7 +81,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn } if container.Hostname != "" { - if err := system.Sethostname(container.Hostname); err != nil { + if err := syscall.Sethostname([]byte(container.Hostname)); err != nil { return fmt.Errorf("sethostname %s", err) } } @@ -155,15 +155,19 @@ func SetupUser(u string) error { if err != nil { return fmt.Errorf("get supplementary groups %s", err) } - if err := system.Setgroups(suppGids); err != nil { + + if err := syscall.Setgroups(suppGids); err != nil { return fmt.Errorf("setgroups %s", err) } - if err := system.Setgid(gid); err != nil { + + if err := syscall.Setgid(gid); err != nil { return fmt.Errorf("setgid %s", err) } - if err := system.Setuid(uid); err != nil { + + if err := syscall.Setuid(uid); err != nil { return fmt.Errorf("setuid %s", err) } + return nil } @@ -229,7 +233,7 @@ func FinalizeNamespace(container *libcontainer.Config) error { } if container.WorkingDir != "" { - if err := system.Chdir(container.WorkingDir); err != nil { + if err := syscall.Chdir(container.WorkingDir); err != nil { return fmt.Errorf("chdir to %s %s", container.WorkingDir, err) } } diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/std_term.go b/vendor/src/github.com/docker/libcontainer/namespaces/std_term.go deleted file mode 100644 index 324336af28..0000000000 --- a/vendor/src/github.com/docker/libcontainer/namespaces/std_term.go +++ /dev/null @@ -1,49 +0,0 @@ -package namespaces - -import ( - "io" - "os" - "os/exec" -) - -type StdTerminal struct { - stdin io.Reader - stdout, stderr io.Writer -} - -func (s *StdTerminal) SetMaster(*os.File) { - // no need to set master on non tty -} - -func (s *StdTerminal) Close() error { - return nil -} - -func (s *StdTerminal) Resize(h, w int) error { - return nil -} - -func (s *StdTerminal) Attach(command *exec.Cmd) error { - inPipe, err := command.StdinPipe() - if err != nil { - return err - } - outPipe, err := command.StdoutPipe() - if err != nil { - return err - } - errPipe, err := command.StderrPipe() - if err != nil { - return err - } - - go func() { - defer inPipe.Close() - io.Copy(inPipe, s.stdin) - }() - - go io.Copy(s.stdout, outPipe) - go io.Copy(s.stderr, errPipe) - - return nil -} diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/term.go b/vendor/src/github.com/docker/libcontainer/namespaces/term.go deleted file mode 100644 index 2a50bf8554..0000000000 --- a/vendor/src/github.com/docker/libcontainer/namespaces/term.go +++ /dev/null @@ -1,29 +0,0 @@ -package namespaces - -import ( - "io" - "os" - "os/exec" -) - -type Terminal interface { - io.Closer - SetMaster(*os.File) - Attach(*exec.Cmd) error - Resize(h, w int) error -} - -func NewTerminal(stdin io.Reader, stdout, stderr io.Writer, tty bool) Terminal { - if tty { - return &TtyTerminal{ - stdin: stdin, - stdout: stdout, - stderr: stderr, - } - } - return &StdTerminal{ - stdin: stdin, - stdout: stdout, - stderr: stderr, - } -} diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/tty_term.go b/vendor/src/github.com/docker/libcontainer/namespaces/tty_term.go deleted file mode 100644 index 272cf2cd65..0000000000 --- a/vendor/src/github.com/docker/libcontainer/namespaces/tty_term.go +++ /dev/null @@ -1,56 +0,0 @@ -package namespaces - -import ( - "io" - "os" - "os/exec" - - "github.com/dotcloud/docker/pkg/term" -) - -type TtyTerminal struct { - stdin io.Reader - stdout, stderr io.Writer - master *os.File - state *term.State -} - -func (t *TtyTerminal) Resize(h, w int) error { - return term.SetWinsize(t.master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) -} - -func (t *TtyTerminal) SetMaster(master *os.File) { - t.master = master -} - -func (t *TtyTerminal) Attach(command *exec.Cmd) error { - go io.Copy(t.stdout, t.master) - go io.Copy(t.master, t.stdin) - - state, err := t.setupWindow(t.master, os.Stdin) - - if err != nil { - return err - } - - t.state = state - return err -} - -// SetupWindow gets the parent window size and sets the master -// pty to the current size and set the parents mode to RAW -func (t *TtyTerminal) setupWindow(master, parent *os.File) (*term.State, error) { - ws, err := term.GetWinsize(parent.Fd()) - if err != nil { - return nil, err - } - if err := term.SetWinsize(master.Fd(), ws); err != nil { - return nil, err - } - return term.SetRawTerminal(parent.Fd()) -} - -func (t *TtyTerminal) Close() error { - term.RestoreTerminal(os.Stdin.Fd(), t.state) - return t.master.Close() -} diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/unsupported.go b/vendor/src/github.com/docker/libcontainer/namespaces/unsupported.go deleted file mode 100644 index 8398b94d7d..0000000000 --- a/vendor/src/github.com/docker/libcontainer/namespaces/unsupported.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build !linux - -package namespaces - -import ( - "github.com/docker/libcontainer" - "github.com/docker/libcontainer/cgroups" -) - -func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { - return -1, ErrUnsupported -} - -func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error { - return ErrUnsupported -} - -func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *SyncPipe) error { - return ErrUnsupported -} - -func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) { - return nil, ErrUnsupported -} - -func GetNamespaceFlags(namespaces map[string]bool) (flag int) { - return 0 -} diff --git a/vendor/src/github.com/docker/libcontainer/network/loopback.go b/vendor/src/github.com/docker/libcontainer/network/loopback.go index 46a1fa8c86..1667b4d82a 100644 --- a/vendor/src/github.com/docker/libcontainer/network/loopback.go +++ b/vendor/src/github.com/docker/libcontainer/network/loopback.go @@ -15,9 +15,7 @@ func (l *Loopback) Create(n *Network, nspid int, networkState *NetworkState) err } func (l *Loopback) Initialize(config *Network, networkState *NetworkState) error { - if err := SetMtu("lo", config.Mtu); err != nil { - return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err) - } + // Do not set the MTU on the loopback interface - use the default. if err := InterfaceUp("lo"); err != nil { return fmt.Errorf("lo up %s", err) } diff --git a/vendor/src/github.com/docker/libcontainer/network/netns.go b/vendor/src/github.com/docker/libcontainer/network/netns.go index 64544476b8..1ff7506452 100644 --- a/vendor/src/github.com/docker/libcontainer/network/netns.go +++ b/vendor/src/github.com/docker/libcontainer/network/netns.go @@ -7,7 +7,7 @@ import ( "os" "syscall" - "github.com/dotcloud/docker/pkg/system" + "github.com/docker/libcontainer/system" ) // crosbymichael: could make a network strategy that instead of returning veth pair names it returns a pid to an existing network namespace @@ -23,12 +23,15 @@ func (v *NetNS) Initialize(config *Network, networkState *NetworkState) error { if networkState.NsPath == "" { return fmt.Errorf("nspath does is not specified in NetworkState") } + f, err := os.OpenFile(networkState.NsPath, os.O_RDONLY, 0) if err != nil { return fmt.Errorf("failed get network namespace fd: %v", err) } + if err := system.Setns(f.Fd(), syscall.CLONE_NEWNET); err != nil { return fmt.Errorf("failed to setns current network namespace: %v", err) } + return nil } diff --git a/vendor/src/github.com/docker/libcontainer/network/types.go b/vendor/src/github.com/docker/libcontainer/network/types.go index 0f1df30e85..3b7a4e395c 100644 --- a/vendor/src/github.com/docker/libcontainer/network/types.go +++ b/vendor/src/github.com/docker/libcontainer/network/types.go @@ -25,6 +25,7 @@ type Network struct { // Mtu sets the mtu value for the interface and will be mirrored on both the host and // container's interfaces if a pair is created, specifically in the case of type veth + // Note: This does not apply to loopback interfaces. Mtu int `json:"mtu,omitempty"` } diff --git a/vendor/src/github.com/docker/libcontainer/nsinit/exec.go b/vendor/src/github.com/docker/libcontainer/nsinit/exec.go index eb734545b5..690af5f5eb 100644 --- a/vendor/src/github.com/docker/libcontainer/nsinit/exec.go +++ b/vendor/src/github.com/docker/libcontainer/nsinit/exec.go @@ -2,14 +2,18 @@ package nsinit import ( "fmt" + "io" "log" "os" "os/exec" "os/signal" + "syscall" "github.com/codegangsta/cli" "github.com/docker/libcontainer" + consolepkg "github.com/docker/libcontainer/console" "github.com/docker/libcontainer/namespaces" + "github.com/dotcloud/docker/pkg/term" ) var execCommand = cli.Command{ @@ -34,8 +38,7 @@ func execAction(context *cli.Context) { if state != nil { err = namespaces.ExecIn(container, state, []string(context.Args())) } else { - term := namespaces.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty) - exitCode, err = startContainer(container, term, dataPath, []string(context.Args())) + exitCode, err = startContainer(container, dataPath, []string(context.Args())) } if err != nil { @@ -49,7 +52,7 @@ func execAction(context *cli.Context) { // error. // // Signals sent to the current process will be forwarded to container. -func startContainer(container *libcontainer.Config, term namespaces.Terminal, dataPath string, args []string) (int, error) { +func startContainer(container *libcontainer.Config, dataPath string, args []string) (int, error) { var ( cmd *exec.Cmd sigc = make(chan os.Signal, 10) @@ -65,13 +68,66 @@ func startContainer(container *libcontainer.Config, term namespaces.Terminal, da return cmd } + var ( + master *os.File + console string + err error + + stdin = os.Stdin + stdout = os.Stdout + stderr = os.Stderr + ) + + if container.Tty { + stdin = nil + stdout = nil + stderr = nil + + master, console, err = consolepkg.CreateMasterAndConsole() + if err != nil { + return -1, err + } + + go io.Copy(master, os.Stdin) + go io.Copy(os.Stdout, master) + + state, err := term.SetRawTerminal(os.Stdin.Fd()) + if err != nil { + return -1, err + } + + defer term.RestoreTerminal(os.Stdin.Fd(), state) + } + startCallback := func() { go func() { + resizeTty(master) + for sig := range sigc { - cmd.Process.Signal(sig) + switch sig { + case syscall.SIGWINCH: + resizeTty(master) + default: + cmd.Process.Signal(sig) + } } }() } - return namespaces.Exec(container, term, "", dataPath, args, createCommand, startCallback) + return namespaces.Exec(container, stdin, stdout, stderr, console, "", dataPath, args, createCommand, startCallback) +} + +func resizeTty(master *os.File) { + if master == nil { + return + } + + ws, err := term.GetWinsize(os.Stdin.Fd()) + if err != nil { + return + } + + if err := term.SetWinsize(master.Fd(), ws); err != nil { + return + } } diff --git a/vendor/src/github.com/docker/libcontainer/security/restrict/restrict.go b/vendor/src/github.com/docker/libcontainer/security/restrict/restrict.go index ff7ae2fec6..dd765b1f1b 100644 --- a/vendor/src/github.com/docker/libcontainer/security/restrict/restrict.go +++ b/vendor/src/github.com/docker/libcontainer/security/restrict/restrict.go @@ -7,23 +7,21 @@ import ( "os" "syscall" "time" - - "github.com/dotcloud/docker/pkg/system" ) const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV func mountReadonly(path string) error { for i := 0; i < 5; i++ { - if err := system.Mount("", path, "", syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil && !os.IsNotExist(err) { + if err := syscall.Mount("", path, "", syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil && !os.IsNotExist(err) { switch err { case syscall.EINVAL: // Probably not a mountpoint, use bind-mount - if err := system.Mount(path, path, "", syscall.MS_BIND, ""); err != nil { + if err := syscall.Mount(path, path, "", syscall.MS_BIND, ""); err != nil { return err } - return system.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC|defaultMountFlags, "") + return syscall.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC|defaultMountFlags, "") case syscall.EBUSY: time.Sleep(100 * time.Millisecond) continue @@ -47,7 +45,7 @@ func Restrict(mounts ...string) error { } } - if err := system.Mount("/dev/null", "/proc/kcore", "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { + if err := syscall.Mount("/dev/null", "/proc/kcore", "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { return fmt.Errorf("unable to bind-mount /dev/null over /proc/kcore: %s", err) } diff --git a/vendor/src/github.com/docker/libcontainer/selinux/selinux.go b/vendor/src/github.com/docker/libcontainer/selinux/selinux.go index 709eb9d815..8dbdbdbc21 100644 --- a/vendor/src/github.com/docker/libcontainer/selinux/selinux.go +++ b/vendor/src/github.com/docker/libcontainer/selinux/selinux.go @@ -5,8 +5,6 @@ import ( "crypto/rand" "encoding/binary" "fmt" - "github.com/dotcloud/docker/pkg/mount" - "github.com/dotcloud/docker/pkg/system" "io" "os" "path/filepath" @@ -14,6 +12,9 @@ import ( "strconv" "strings" "syscall" + + "github.com/docker/libcontainer/system" + "github.com/dotcloud/docker/pkg/mount" ) const ( @@ -153,16 +154,16 @@ func Getfilecon(path string) (string, error) { } func Setfscreatecon(scon string) error { - return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon) + return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), scon) } func Getfscreatecon() (string, error) { - return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid())) + return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid())) } // Return the SELinux label of the current process thread. func Getcon() (string, error) { - return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid())) + return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid())) } func Getpidcon(pid int) (string, error) { @@ -192,7 +193,7 @@ func writeCon(name string, val string) error { } func Setexeccon(scon string) error { - return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", system.Gettid()), scon) + return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), scon) } func (c SELinuxContext) Get() string { diff --git a/vendor/src/github.com/docker/libcontainer/system/linux.go b/vendor/src/github.com/docker/libcontainer/system/linux.go new file mode 100644 index 0000000000..c07ef1532d --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/system/linux.go @@ -0,0 +1,60 @@ +// +build linux + +package system + +import ( + "os/exec" + "syscall" + "unsafe" +) + +func Execv(cmd string, args []string, env []string) error { + name, err := exec.LookPath(cmd) + if err != nil { + return err + } + + return syscall.Exec(name, args, env) +} + +func ParentDeathSignal(sig uintptr) error { + if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 { + return err + } + return nil +} + +func GetParentDeathSignal() (int, error) { + var sig int + + _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) + + if err != 0 { + return -1, err + } + + return sig, nil +} + +func SetKeepCaps() error { + if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 { + return err + } + + return nil +} + +func ClearKeepCaps() error { + if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 { + return err + } + + return nil +} + +func Setctty() error { + if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 { + return err + } + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/system/proc.go b/vendor/src/github.com/docker/libcontainer/system/proc.go new file mode 100644 index 0000000000..37808a29f6 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/system/proc.go @@ -0,0 +1,27 @@ +package system + +import ( + "io/ioutil" + "path/filepath" + "strconv" + "strings" +) + +// look in /proc to find the process start time so that we can verify +// that this pid has started after ourself +func GetProcessStartTime(pid int) (string, error) { + data, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) + if err != nil { + return "", err + } + + parts := strings.Split(string(data), " ") + // the starttime is located at pos 22 + // from the man page + // + // starttime %llu (was %lu before Linux 2.6) + // (22) The time the process started after system boot. In kernels before Linux 2.6, this + // value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks + // (divide by sysconf(_SC_CLK_TCK)). + return parts[22-1], nil // starts at 1 +} diff --git a/vendor/src/github.com/docker/libcontainer/system/setns_linux.go b/vendor/src/github.com/docker/libcontainer/system/setns_linux.go new file mode 100644 index 0000000000..a0a259e170 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/system/setns_linux.go @@ -0,0 +1,29 @@ +package system + +import ( + "fmt" + "runtime" + "syscall" +) + +// Via http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7b21fddd087678a70ad64afc0f632e0f1071b092 +// +// We need different setns values for the different platforms and arch +// We are declaring the macro here because the SETNS syscall does not exist in th stdlib +var setNsMap = map[string]uintptr{ + "linux/amd64": 308, +} + +func Setns(fd uintptr, flags uintptr) error { + ns, exists := setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)] + if !exists { + return fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime.GOARCH) + } + + _, _, err := syscall.RawSyscall(ns, fd, flags, 0) + if err != 0 { + return err + } + + return nil +} diff --git a/vendor/src/github.com/docker/libcontainer/system/sysconfig.go b/vendor/src/github.com/docker/libcontainer/system/sysconfig.go new file mode 100644 index 0000000000..dcbe6c9cdd --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/system/sysconfig.go @@ -0,0 +1,13 @@ +// +build linux,cgo + +package system + +/* +#include +int get_hz(void) { return sysconf(_SC_CLK_TCK); } +*/ +import "C" + +func GetClockTicks() int { + return int(C.get_hz()) +} diff --git a/vendor/src/github.com/docker/libcontainer/system/xattrs_linux.go b/vendor/src/github.com/docker/libcontainer/system/xattrs_linux.go new file mode 100644 index 0000000000..00edb201b5 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/system/xattrs_linux.go @@ -0,0 +1,59 @@ +package system + +import ( + "syscall" + "unsafe" +) + +// Returns a nil slice and nil error if the xattr is not set +func Lgetxattr(path string, attr string) ([]byte, error) { + pathBytes, err := syscall.BytePtrFromString(path) + if err != nil { + return nil, err + } + attrBytes, err := syscall.BytePtrFromString(attr) + if err != nil { + return nil, err + } + + dest := make([]byte, 128) + destBytes := unsafe.Pointer(&dest[0]) + sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + if errno == syscall.ENODATA { + return nil, nil + } + if errno == syscall.ERANGE { + dest = make([]byte, sz) + destBytes := unsafe.Pointer(&dest[0]) + sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + } + if errno != 0 { + return nil, errno + } + + return dest[:sz], nil +} + +var _zero uintptr + +func Lsetxattr(path string, attr string, data []byte, flags int) error { + pathBytes, err := syscall.BytePtrFromString(path) + if err != nil { + return err + } + attrBytes, err := syscall.BytePtrFromString(attr) + if err != nil { + return err + } + var dataBytes unsafe.Pointer + if len(data) > 0 { + dataBytes = unsafe.Pointer(&data[0]) + } else { + dataBytes = unsafe.Pointer(&_zero) + } + _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) + if errno != 0 { + return errno + } + return nil +}