Browse code

Update libcontainer to be85764f109c3f0f62cd2a5c8be Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@docker.com> (github: crosbymichael)

Michael Crosby authored on 2014/07/17 07:15:29
Showing 29 changed files
... ...
@@ -63,4 +63,4 @@ mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
63 63
 
64 64
 clone git github.com/godbus/dbus v1
65 65
 clone git github.com/coreos/go-systemd v2
66
-clone git github.com/docker/libcontainer fb67bb80b4205bece36ff7096ee745ab0cee7e06
66
+clone git github.com/docker/libcontainer be85764f109c3f0f62cd2a5c8be9af7a599798cf
67 67
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+FROM crosbymichael/golang
1
+
2
+RUN apt-get update && apt-get install -y gcc
3
+
4
+ADD . /go/src/github.com/docker/libcontainer
5
+RUN cd /go/src/github.com/docker/libcontainer && go get -d ./... && go install ./...
6
+
7
+CMD ["nsinit"]
... ...
@@ -12,7 +12,7 @@ import (
12 12
 	"time"
13 13
 
14 14
 	"github.com/docker/libcontainer/cgroups"
15
-	"github.com/dotcloud/docker/pkg/system"
15
+	"github.com/docker/libcontainer/system"
16 16
 )
17 17
 
18 18
 var (
... ...
@@ -7,22 +7,24 @@ import (
7 7
 	"os"
8 8
 	"path/filepath"
9 9
 	"syscall"
10
+	"unsafe"
10 11
 
11 12
 	"github.com/docker/libcontainer/label"
12
-	"github.com/dotcloud/docker/pkg/system"
13 13
 )
14 14
 
15 15
 // Setup initializes the proper /dev/console inside the rootfs path
16 16
 func Setup(rootfs, consolePath, mountLabel string) error {
17
-	oldMask := system.Umask(0000)
18
-	defer system.Umask(oldMask)
17
+	oldMask := syscall.Umask(0000)
18
+	defer syscall.Umask(oldMask)
19 19
 
20 20
 	if err := os.Chmod(consolePath, 0600); err != nil {
21 21
 		return err
22 22
 	}
23
+
23 24
 	if err := os.Chown(consolePath, 0, 0); err != nil {
24 25
 		return err
25 26
 	}
27
+
26 28
 	if err := label.SetFileLabel(consolePath, mountLabel); err != nil {
27 29
 		return fmt.Errorf("set file label %s %s", consolePath, err)
28 30
 	}
... ...
@@ -33,26 +35,94 @@ func Setup(rootfs, consolePath, mountLabel string) error {
33 33
 	if err != nil && !os.IsExist(err) {
34 34
 		return fmt.Errorf("create %s %s", dest, err)
35 35
 	}
36
+
36 37
 	if f != nil {
37 38
 		f.Close()
38 39
 	}
39 40
 
40
-	if err := system.Mount(consolePath, dest, "bind", syscall.MS_BIND, ""); err != nil {
41
+	if err := syscall.Mount(consolePath, dest, "bind", syscall.MS_BIND, ""); err != nil {
41 42
 		return fmt.Errorf("bind %s to %s %s", consolePath, dest, err)
42 43
 	}
44
+
43 45
 	return nil
44 46
 }
45 47
 
46 48
 func OpenAndDup(consolePath string) error {
47
-	slave, err := system.OpenTerminal(consolePath, syscall.O_RDWR)
49
+	slave, err := OpenTerminal(consolePath, syscall.O_RDWR)
48 50
 	if err != nil {
49 51
 		return fmt.Errorf("open terminal %s", err)
50 52
 	}
51
-	if err := system.Dup2(slave.Fd(), 0); err != nil {
53
+
54
+	if err := syscall.Dup2(int(slave.Fd()), 0); err != nil {
52 55
 		return err
53 56
 	}
54
-	if err := system.Dup2(slave.Fd(), 1); err != nil {
57
+
58
+	if err := syscall.Dup2(int(slave.Fd()), 1); err != nil {
59
+		return err
60
+	}
61
+
62
+	return syscall.Dup2(int(slave.Fd()), 2)
63
+}
64
+
65
+// Unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
66
+// Unlockpt should be called before opening the slave side of a pseudoterminal.
67
+func Unlockpt(f *os.File) error {
68
+	var u int
69
+
70
+	return Ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
71
+}
72
+
73
+// Ptsname retrieves the name of the first available pts for the given master.
74
+func Ptsname(f *os.File) (string, error) {
75
+	var n int
76
+
77
+	if err := Ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))); err != nil {
78
+		return "", err
79
+	}
80
+
81
+	return fmt.Sprintf("/dev/pts/%d", n), nil
82
+}
83
+
84
+// CreateMasterAndConsole will open /dev/ptmx on the host and retreive the
85
+// pts name for use as the pty slave inside the container
86
+func CreateMasterAndConsole() (*os.File, string, error) {
87
+	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
88
+	if err != nil {
89
+		return nil, "", err
90
+	}
91
+
92
+	console, err := Ptsname(master)
93
+	if err != nil {
94
+		return nil, "", err
95
+	}
96
+
97
+	if err := Unlockpt(master); err != nil {
98
+		return nil, "", err
99
+	}
100
+
101
+	return master, console, nil
102
+}
103
+
104
+// OpenPtmx opens /dev/ptmx, i.e. the PTY master.
105
+func OpenPtmx() (*os.File, error) {
106
+	// O_NOCTTY and O_CLOEXEC are not present in os package so we use the syscall's one for all.
107
+	return os.OpenFile("/dev/ptmx", syscall.O_RDONLY|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
108
+}
109
+
110
+// OpenTerminal is a clone of os.OpenFile without the O_CLOEXEC
111
+// used to open the pty slave inside the container namespace
112
+func OpenTerminal(name string, flag int) (*os.File, error) {
113
+	r, e := syscall.Open(name, flag, 0)
114
+	if e != nil {
115
+		return nil, &os.PathError{"open", name, e}
116
+	}
117
+	return os.NewFile(uintptr(r), name), nil
118
+}
119
+
120
+func Ioctl(fd uintptr, flag, data uintptr) error {
121
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, flag, data); err != 0 {
55 122
 		return err
56 123
 	}
57
-	return system.Dup2(slave.Fd(), 2)
124
+
125
+	return nil
58 126
 }
... ...
@@ -11,7 +11,6 @@ import (
11 11
 	"github.com/docker/libcontainer/label"
12 12
 	"github.com/docker/libcontainer/mount/nodes"
13 13
 	"github.com/dotcloud/docker/pkg/symlink"
14
-	"github.com/dotcloud/docker/pkg/system"
15 14
 )
16 15
 
17 16
 // default mount point flags
... ...
@@ -35,10 +34,10 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig)
35 35
 	if mountConfig.NoPivotRoot {
36 36
 		flag = syscall.MS_SLAVE
37 37
 	}
38
-	if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil {
38
+	if err := syscall.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil {
39 39
 		return fmt.Errorf("mounting / with flags %X %s", (flag | syscall.MS_REC), err)
40 40
 	}
41
-	if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
41
+	if err := syscall.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
42 42
 		return fmt.Errorf("mouting %s as bind %s", rootfs, err)
43 43
 	}
44 44
 	if err := mountSystem(rootfs, mountConfig); err != nil {
... ...
@@ -56,7 +55,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig)
56 56
 	if err := setupDevSymlinks(rootfs); err != nil {
57 57
 		return fmt.Errorf("dev symlinks %s", err)
58 58
 	}
59
-	if err := system.Chdir(rootfs); err != nil {
59
+	if err := syscall.Chdir(rootfs); err != nil {
60 60
 		return fmt.Errorf("chdir into %s %s", rootfs, err)
61 61
 	}
62 62
 
... ...
@@ -75,7 +74,7 @@ func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig)
75 75
 		}
76 76
 	}
77 77
 
78
-	system.Umask(0022)
78
+	syscall.Umask(0022)
79 79
 
80 80
 	return nil
81 81
 }
... ...
@@ -87,7 +86,7 @@ func mountSystem(rootfs string, mountConfig *MountConfig) error {
87 87
 		if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) {
88 88
 			return fmt.Errorf("mkdirall %s %s", m.path, err)
89 89
 		}
90
-		if err := system.Mount(m.source, m.path, m.device, uintptr(m.flags), m.data); err != nil {
90
+		if err := syscall.Mount(m.source, m.path, m.device, uintptr(m.flags), m.data); err != nil {
91 91
 			return fmt.Errorf("mounting %s into %s %s", m.source, m.path, err)
92 92
 		}
93 93
 	}
... ...
@@ -169,11 +168,11 @@ func setupBindmounts(rootfs string, mountConfig *MountConfig) error {
169 169
 			return fmt.Errorf("Creating new bind-mount target, %s", err)
170 170
 		}
171 171
 
172
-		if err := system.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
172
+		if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
173 173
 			return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err)
174 174
 		}
175 175
 		if !m.Writable {
176
-			if err := system.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
176
+			if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
177 177
 				return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
178 178
 			}
179 179
 		}
... ...
@@ -183,7 +182,7 @@ func setupBindmounts(rootfs string, mountConfig *MountConfig) error {
183 183
 			}
184 184
 		}
185 185
 		if m.Private {
186
-			if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
186
+			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
187 187
 				return fmt.Errorf("mounting %s private %s", dest, err)
188 188
 			}
189 189
 		}
... ...
@@ -4,16 +4,17 @@ package mount
4 4
 
5 5
 import (
6 6
 	"fmt"
7
-	"github.com/dotcloud/docker/pkg/system"
8 7
 	"syscall"
9 8
 )
10 9
 
11 10
 func MsMoveRoot(rootfs string) error {
12
-	if err := system.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil {
11
+	if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil {
13 12
 		return fmt.Errorf("mount move %s into / %s", rootfs, err)
14 13
 	}
15
-	if err := system.Chroot("."); err != nil {
14
+
15
+	if err := syscall.Chroot("."); err != nil {
16 16
 		return fmt.Errorf("chroot . %s", err)
17 17
 	}
18
-	return system.Chdir("/")
18
+
19
+	return syscall.Chdir("/")
19 20
 }
... ...
@@ -9,13 +9,12 @@ import (
9 9
 	"syscall"
10 10
 
11 11
 	"github.com/docker/libcontainer/devices"
12
-	"github.com/dotcloud/docker/pkg/system"
13 12
 )
14 13
 
15 14
 // Create the device nodes in the container.
16 15
 func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error {
17
-	oldMask := system.Umask(0000)
18
-	defer system.Umask(oldMask)
16
+	oldMask := syscall.Umask(0000)
17
+	defer syscall.Umask(oldMask)
19 18
 
20 19
 	for _, node := range nodesToCreate {
21 20
 		if err := CreateDeviceNode(rootfs, node); err != nil {
... ...
@@ -46,7 +45,7 @@ func CreateDeviceNode(rootfs string, node *devices.Device) error {
46 46
 		return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path)
47 47
 	}
48 48
 
49
-	if err := system.Mknod(dest, uint32(fileMode), devices.Mkdev(node.MajorNumber, node.MinorNumber)); err != nil && !os.IsExist(err) {
49
+	if err := syscall.Mknod(dest, uint32(fileMode), devices.Mkdev(node.MajorNumber, node.MinorNumber)); err != nil && !os.IsExist(err) {
50 50
 		return fmt.Errorf("mknod %s %s", node.Path, err)
51 51
 	}
52 52
 	return nil
... ...
@@ -8,8 +8,6 @@ import (
8 8
 	"os"
9 9
 	"path/filepath"
10 10
 	"syscall"
11
-
12
-	"github.com/dotcloud/docker/pkg/system"
13 11
 )
14 12
 
15 13
 func PivotRoot(rootfs string) error {
... ...
@@ -17,16 +15,20 @@ func PivotRoot(rootfs string) error {
17 17
 	if err != nil {
18 18
 		return fmt.Errorf("can't create pivot_root dir %s, error %v", pivotDir, err)
19 19
 	}
20
-	if err := system.Pivotroot(rootfs, pivotDir); err != nil {
20
+
21
+	if err := syscall.PivotRoot(rootfs, pivotDir); err != nil {
21 22
 		return fmt.Errorf("pivot_root %s", err)
22 23
 	}
23
-	if err := system.Chdir("/"); err != nil {
24
+
25
+	if err := syscall.Chdir("/"); err != nil {
24 26
 		return fmt.Errorf("chdir / %s", err)
25 27
 	}
28
+
26 29
 	// path to pivot dir now changed, update
27 30
 	pivotDir = filepath.Join("/", filepath.Base(pivotDir))
28
-	if err := system.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {
31
+	if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {
29 32
 		return fmt.Errorf("unmount pivot_root dir %s", err)
30 33
 	}
34
+
31 35
 	return os.Remove(pivotDir)
32 36
 }
... ...
@@ -4,9 +4,10 @@ package mount
4 4
 
5 5
 import (
6 6
 	"fmt"
7
-	"github.com/docker/libcontainer/console"
8 7
 	"os"
9 8
 	"path/filepath"
9
+
10
+	"github.com/docker/libcontainer/console"
10 11
 )
11 12
 
12 13
 func SetupPtmx(rootfs, consolePath, mountLabel string) error {
... ...
@@ -14,13 +15,16 @@ func SetupPtmx(rootfs, consolePath, mountLabel string) error {
14 14
 	if err := os.Remove(ptmx); err != nil && !os.IsNotExist(err) {
15 15
 		return err
16 16
 	}
17
+
17 18
 	if err := os.Symlink("pts/ptmx", ptmx); err != nil {
18 19
 		return fmt.Errorf("symlink dev ptmx %s", err)
19 20
 	}
21
+
20 22
 	if consolePath != "" {
21 23
 		if err := console.Setup(rootfs, consolePath, mountLabel); err != nil {
22 24
 			return err
23 25
 		}
24 26
 	}
27
+
25 28
 	return nil
26 29
 }
... ...
@@ -3,10 +3,9 @@
3 3
 package mount
4 4
 
5 5
 import (
6
-	"github.com/dotcloud/docker/pkg/system"
7 6
 	"syscall"
8 7
 )
9 8
 
10 9
 func SetReadonly() error {
11
-	return system.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "")
10
+	return syscall.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "")
12 11
 }
... ...
@@ -2,30 +2,30 @@
2 2
 
3 3
 package mount
4 4
 
5
-import (
6
-	"github.com/dotcloud/docker/pkg/system"
7
-	"syscall"
8
-)
5
+import "syscall"
9 6
 
10 7
 func RemountProc() error {
11
-	if err := system.Unmount("/proc", syscall.MNT_DETACH); err != nil {
8
+	if err := syscall.Unmount("/proc", syscall.MNT_DETACH); err != nil {
12 9
 		return err
13 10
 	}
14
-	if err := system.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), ""); err != nil {
11
+
12
+	if err := syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), ""); err != nil {
15 13
 		return err
16 14
 	}
15
+
17 16
 	return nil
18 17
 }
19 18
 
20 19
 func RemountSys() error {
21
-	if err := system.Unmount("/sys", syscall.MNT_DETACH); err != nil {
20
+	if err := syscall.Unmount("/sys", syscall.MNT_DETACH); err != nil {
22 21
 		if err != syscall.EINVAL {
23 22
 			return err
24 23
 		}
25 24
 	} else {
26
-		if err := system.Mount("sysfs", "/sys", "sysfs", uintptr(defaultMountFlags), ""); err != nil {
25
+		if err := syscall.Mount("sysfs", "/sys", "sysfs", uintptr(defaultMountFlags), ""); err != nil {
27 26
 			return err
28 27
 		}
29 28
 	}
29
+
30 30
 	return nil
31 31
 }
... ...
@@ -3,6 +3,7 @@
3 3
 package namespaces
4 4
 
5 5
 import (
6
+	"io"
6 7
 	"os"
7 8
 	"os/exec"
8 9
 	"syscall"
... ...
@@ -13,18 +14,16 @@ import (
13 13
 	"github.com/docker/libcontainer/cgroups/systemd"
14 14
 	"github.com/docker/libcontainer/network"
15 15
 	"github.com/docker/libcontainer/syncpipe"
16
-	"github.com/dotcloud/docker/pkg/system"
16
+	"github.com/docker/libcontainer/system"
17 17
 )
18 18
 
19 19
 // TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work.
20 20
 // Move this to libcontainer package.
21 21
 // Exec performs setup outside of a namespace so that a container can be
22 22
 // executed.  Exec is a high level function for working with container namespaces.
23
-func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
23
+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) {
24 24
 	var (
25
-		master  *os.File
26
-		console string
27
-		err     error
25
+		err error
28 26
 	)
29 27
 
30 28
 	// 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
35 35
 	}
36 36
 	defer syncPipe.Close()
37 37
 
38
-	if container.Tty {
39
-		master, console, err = system.CreateMasterAndConsole()
40
-		if err != nil {
41
-			return -1, err
42
-		}
43
-		term.SetMaster(master)
44
-	}
45
-
46 38
 	command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.Child(), args)
47
-
48
-	if err := term.Attach(command); err != nil {
49
-		return -1, err
50
-	}
51
-	defer term.Close()
39
+	// Note: these are only used in non-tty mode
40
+	// if there is a tty for the container it will be opened within the namespace and the
41
+	// fds will be duped to stdin, stdiout, and stderr
42
+	command.Stdin = stdin
43
+	command.Stdout = stdout
44
+	command.Stderr = stderr
52 45
 
53 46
 	if err := command.Start(); err != nil {
54 47
 		return -1, err
... ...
@@ -110,6 +102,7 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string
110 110
 			return -1, err
111 111
 		}
112 112
 	}
113
+
113 114
 	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
114 115
 }
115 116
 
... ...
@@ -145,7 +138,11 @@ func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataP
145 145
 	command.Dir = rootfs
146 146
 	command.Env = append(os.Environ(), env...)
147 147
 
148
-	system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces)))
148
+	if command.SysProcAttr == nil {
149
+		command.SysProcAttr = &syscall.SysProcAttr{}
150
+	}
151
+	command.SysProcAttr.Cloneflags = uintptr(GetNamespaceFlags(container.Namespaces))
152
+
149 153
 	command.SysProcAttr.Pdeathsig = syscall.SIGKILL
150 154
 	command.ExtraFiles = []*os.File{pipe}
151 155
 
... ...
@@ -157,11 +154,14 @@ func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataP
157 157
 func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) {
158 158
 	if container.Cgroups != nil {
159 159
 		c := container.Cgroups
160
+
160 161
 		if systemd.UseSystemd() {
161 162
 			return systemd.Apply(c, nspid)
162 163
 		}
164
+
163 165
 		return fs.Apply(c, nspid)
164 166
 	}
167
+
165 168
 	return nil, nil
166 169
 }
167 170
 
... ...
@@ -9,7 +9,7 @@ import (
9 9
 
10 10
 	"github.com/docker/libcontainer"
11 11
 	"github.com/docker/libcontainer/label"
12
-	"github.com/dotcloud/docker/pkg/system"
12
+	"github.com/docker/libcontainer/system"
13 13
 )
14 14
 
15 15
 // ExecIn uses an existing pid and joins the pid's namespaces with the new command.
... ...
@@ -19,8 +19,8 @@ import (
19 19
 	"github.com/docker/libcontainer/security/capabilities"
20 20
 	"github.com/docker/libcontainer/security/restrict"
21 21
 	"github.com/docker/libcontainer/syncpipe"
22
+	"github.com/docker/libcontainer/system"
22 23
 	"github.com/docker/libcontainer/utils"
23
-	"github.com/dotcloud/docker/pkg/system"
24 24
 	"github.com/dotcloud/docker/pkg/user"
25 25
 )
26 26
 
... ...
@@ -57,7 +57,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn
57 57
 			return err
58 58
 		}
59 59
 	}
60
-	if _, err := system.Setsid(); err != nil {
60
+	if _, err := syscall.Setsid(); err != nil {
61 61
 		return fmt.Errorf("setsid %s", err)
62 62
 	}
63 63
 	if consolePath != "" {
... ...
@@ -81,7 +81,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn
81 81
 	}
82 82
 
83 83
 	if container.Hostname != "" {
84
-		if err := system.Sethostname(container.Hostname); err != nil {
84
+		if err := syscall.Sethostname([]byte(container.Hostname)); err != nil {
85 85
 			return fmt.Errorf("sethostname %s", err)
86 86
 		}
87 87
 	}
... ...
@@ -155,15 +155,19 @@ func SetupUser(u string) error {
155 155
 	if err != nil {
156 156
 		return fmt.Errorf("get supplementary groups %s", err)
157 157
 	}
158
-	if err := system.Setgroups(suppGids); err != nil {
158
+
159
+	if err := syscall.Setgroups(suppGids); err != nil {
159 160
 		return fmt.Errorf("setgroups %s", err)
160 161
 	}
161
-	if err := system.Setgid(gid); err != nil {
162
+
163
+	if err := syscall.Setgid(gid); err != nil {
162 164
 		return fmt.Errorf("setgid %s", err)
163 165
 	}
164
-	if err := system.Setuid(uid); err != nil {
166
+
167
+	if err := syscall.Setuid(uid); err != nil {
165 168
 		return fmt.Errorf("setuid %s", err)
166 169
 	}
170
+
167 171
 	return nil
168 172
 }
169 173
 
... ...
@@ -229,7 +233,7 @@ func FinalizeNamespace(container *libcontainer.Config) error {
229 229
 	}
230 230
 
231 231
 	if container.WorkingDir != "" {
232
-		if err := system.Chdir(container.WorkingDir); err != nil {
232
+		if err := syscall.Chdir(container.WorkingDir); err != nil {
233 233
 			return fmt.Errorf("chdir to %s %s", container.WorkingDir, err)
234 234
 		}
235 235
 	}
236 236
deleted file mode 100644
... ...
@@ -1,49 +0,0 @@
1
-package namespaces
2
-
3
-import (
4
-	"io"
5
-	"os"
6
-	"os/exec"
7
-)
8
-
9
-type StdTerminal struct {
10
-	stdin          io.Reader
11
-	stdout, stderr io.Writer
12
-}
13
-
14
-func (s *StdTerminal) SetMaster(*os.File) {
15
-	// no need to set master on non tty
16
-}
17
-
18
-func (s *StdTerminal) Close() error {
19
-	return nil
20
-}
21
-
22
-func (s *StdTerminal) Resize(h, w int) error {
23
-	return nil
24
-}
25
-
26
-func (s *StdTerminal) Attach(command *exec.Cmd) error {
27
-	inPipe, err := command.StdinPipe()
28
-	if err != nil {
29
-		return err
30
-	}
31
-	outPipe, err := command.StdoutPipe()
32
-	if err != nil {
33
-		return err
34
-	}
35
-	errPipe, err := command.StderrPipe()
36
-	if err != nil {
37
-		return err
38
-	}
39
-
40
-	go func() {
41
-		defer inPipe.Close()
42
-		io.Copy(inPipe, s.stdin)
43
-	}()
44
-
45
-	go io.Copy(s.stdout, outPipe)
46
-	go io.Copy(s.stderr, errPipe)
47
-
48
-	return nil
49
-}
50 1
deleted file mode 100644
... ...
@@ -1,29 +0,0 @@
1
-package namespaces
2
-
3
-import (
4
-	"io"
5
-	"os"
6
-	"os/exec"
7
-)
8
-
9
-type Terminal interface {
10
-	io.Closer
11
-	SetMaster(*os.File)
12
-	Attach(*exec.Cmd) error
13
-	Resize(h, w int) error
14
-}
15
-
16
-func NewTerminal(stdin io.Reader, stdout, stderr io.Writer, tty bool) Terminal {
17
-	if tty {
18
-		return &TtyTerminal{
19
-			stdin:  stdin,
20
-			stdout: stdout,
21
-			stderr: stderr,
22
-		}
23
-	}
24
-	return &StdTerminal{
25
-		stdin:  stdin,
26
-		stdout: stdout,
27
-		stderr: stderr,
28
-	}
29
-}
30 1
deleted file mode 100644
... ...
@@ -1,56 +0,0 @@
1
-package namespaces
2
-
3
-import (
4
-	"io"
5
-	"os"
6
-	"os/exec"
7
-
8
-	"github.com/dotcloud/docker/pkg/term"
9
-)
10
-
11
-type TtyTerminal struct {
12
-	stdin          io.Reader
13
-	stdout, stderr io.Writer
14
-	master         *os.File
15
-	state          *term.State
16
-}
17
-
18
-func (t *TtyTerminal) Resize(h, w int) error {
19
-	return term.SetWinsize(t.master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
20
-}
21
-
22
-func (t *TtyTerminal) SetMaster(master *os.File) {
23
-	t.master = master
24
-}
25
-
26
-func (t *TtyTerminal) Attach(command *exec.Cmd) error {
27
-	go io.Copy(t.stdout, t.master)
28
-	go io.Copy(t.master, t.stdin)
29
-
30
-	state, err := t.setupWindow(t.master, os.Stdin)
31
-
32
-	if err != nil {
33
-		return err
34
-	}
35
-
36
-	t.state = state
37
-	return err
38
-}
39
-
40
-// SetupWindow gets the parent window size and sets the master
41
-// pty to the current size and set the parents mode to RAW
42
-func (t *TtyTerminal) setupWindow(master, parent *os.File) (*term.State, error) {
43
-	ws, err := term.GetWinsize(parent.Fd())
44
-	if err != nil {
45
-		return nil, err
46
-	}
47
-	if err := term.SetWinsize(master.Fd(), ws); err != nil {
48
-		return nil, err
49
-	}
50
-	return term.SetRawTerminal(parent.Fd())
51
-}
52
-
53
-func (t *TtyTerminal) Close() error {
54
-	term.RestoreTerminal(os.Stdin.Fd(), t.state)
55
-	return t.master.Close()
56
-}
57 1
deleted file mode 100644
... ...
@@ -1,28 +0,0 @@
1
-// +build !linux
2
-
3
-package namespaces
4
-
5
-import (
6
-	"github.com/docker/libcontainer"
7
-	"github.com/docker/libcontainer/cgroups"
8
-)
9
-
10
-func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
11
-	return -1, ErrUnsupported
12
-}
13
-
14
-func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
15
-	return ErrUnsupported
16
-}
17
-
18
-func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *SyncPipe) error {
19
-	return ErrUnsupported
20
-}
21
-
22
-func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) {
23
-	return nil, ErrUnsupported
24
-}
25
-
26
-func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
27
-	return 0
28
-}
... ...
@@ -15,9 +15,7 @@ func (l *Loopback) Create(n *Network, nspid int, networkState *NetworkState) err
15 15
 }
16 16
 
17 17
 func (l *Loopback) Initialize(config *Network, networkState *NetworkState) error {
18
-	if err := SetMtu("lo", config.Mtu); err != nil {
19
-		return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err)
20
-	}
18
+	// Do not set the MTU on the loopback interface - use the default.
21 19
 	if err := InterfaceUp("lo"); err != nil {
22 20
 		return fmt.Errorf("lo up %s", err)
23 21
 	}
... ...
@@ -7,7 +7,7 @@ import (
7 7
 	"os"
8 8
 	"syscall"
9 9
 
10
-	"github.com/dotcloud/docker/pkg/system"
10
+	"github.com/docker/libcontainer/system"
11 11
 )
12 12
 
13 13
 //  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 {
23 23
 	if networkState.NsPath == "" {
24 24
 		return fmt.Errorf("nspath does is not specified in NetworkState")
25 25
 	}
26
+
26 27
 	f, err := os.OpenFile(networkState.NsPath, os.O_RDONLY, 0)
27 28
 	if err != nil {
28 29
 		return fmt.Errorf("failed get network namespace fd: %v", err)
29 30
 	}
31
+
30 32
 	if err := system.Setns(f.Fd(), syscall.CLONE_NEWNET); err != nil {
31 33
 		return fmt.Errorf("failed to setns current network namespace: %v", err)
32 34
 	}
35
+
33 36
 	return nil
34 37
 }
... ...
@@ -25,6 +25,7 @@ type Network struct {
25 25
 
26 26
 	// Mtu sets the mtu value for the interface and will be mirrored on both the host and
27 27
 	// container's interfaces if a pair is created, specifically in the case of type veth
28
+	// Note: This does not apply to loopback interfaces.
28 29
 	Mtu int `json:"mtu,omitempty"`
29 30
 }
30 31
 
... ...
@@ -2,14 +2,18 @@ package nsinit
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"io"
5 6
 	"log"
6 7
 	"os"
7 8
 	"os/exec"
8 9
 	"os/signal"
10
+	"syscall"
9 11
 
10 12
 	"github.com/codegangsta/cli"
11 13
 	"github.com/docker/libcontainer"
14
+	consolepkg "github.com/docker/libcontainer/console"
12 15
 	"github.com/docker/libcontainer/namespaces"
16
+	"github.com/dotcloud/docker/pkg/term"
13 17
 )
14 18
 
15 19
 var execCommand = cli.Command{
... ...
@@ -34,8 +38,7 @@ func execAction(context *cli.Context) {
34 34
 	if state != nil {
35 35
 		err = namespaces.ExecIn(container, state, []string(context.Args()))
36 36
 	} else {
37
-		term := namespaces.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
38
-		exitCode, err = startContainer(container, term, dataPath, []string(context.Args()))
37
+		exitCode, err = startContainer(container, dataPath, []string(context.Args()))
39 38
 	}
40 39
 
41 40
 	if err != nil {
... ...
@@ -49,7 +52,7 @@ func execAction(context *cli.Context) {
49 49
 // error.
50 50
 //
51 51
 // Signals sent to the current process will be forwarded to container.
52
-func startContainer(container *libcontainer.Config, term namespaces.Terminal, dataPath string, args []string) (int, error) {
52
+func startContainer(container *libcontainer.Config, dataPath string, args []string) (int, error) {
53 53
 	var (
54 54
 		cmd  *exec.Cmd
55 55
 		sigc = make(chan os.Signal, 10)
... ...
@@ -65,13 +68,66 @@ func startContainer(container *libcontainer.Config, term namespaces.Terminal, da
65 65
 		return cmd
66 66
 	}
67 67
 
68
+	var (
69
+		master  *os.File
70
+		console string
71
+		err     error
72
+
73
+		stdin  = os.Stdin
74
+		stdout = os.Stdout
75
+		stderr = os.Stderr
76
+	)
77
+
78
+	if container.Tty {
79
+		stdin = nil
80
+		stdout = nil
81
+		stderr = nil
82
+
83
+		master, console, err = consolepkg.CreateMasterAndConsole()
84
+		if err != nil {
85
+			return -1, err
86
+		}
87
+
88
+		go io.Copy(master, os.Stdin)
89
+		go io.Copy(os.Stdout, master)
90
+
91
+		state, err := term.SetRawTerminal(os.Stdin.Fd())
92
+		if err != nil {
93
+			return -1, err
94
+		}
95
+
96
+		defer term.RestoreTerminal(os.Stdin.Fd(), state)
97
+	}
98
+
68 99
 	startCallback := func() {
69 100
 		go func() {
101
+			resizeTty(master)
102
+
70 103
 			for sig := range sigc {
71
-				cmd.Process.Signal(sig)
104
+				switch sig {
105
+				case syscall.SIGWINCH:
106
+					resizeTty(master)
107
+				default:
108
+					cmd.Process.Signal(sig)
109
+				}
72 110
 			}
73 111
 		}()
74 112
 	}
75 113
 
76
-	return namespaces.Exec(container, term, "", dataPath, args, createCommand, startCallback)
114
+	return namespaces.Exec(container, stdin, stdout, stderr, console, "", dataPath, args, createCommand, startCallback)
115
+}
116
+
117
+func resizeTty(master *os.File) {
118
+	if master == nil {
119
+		return
120
+	}
121
+
122
+	ws, err := term.GetWinsize(os.Stdin.Fd())
123
+	if err != nil {
124
+		return
125
+	}
126
+
127
+	if err := term.SetWinsize(master.Fd(), ws); err != nil {
128
+		return
129
+	}
77 130
 }
... ...
@@ -7,23 +7,21 @@ import (
7 7
 	"os"
8 8
 	"syscall"
9 9
 	"time"
10
-
11
-	"github.com/dotcloud/docker/pkg/system"
12 10
 )
13 11
 
14 12
 const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
15 13
 
16 14
 func mountReadonly(path string) error {
17 15
 	for i := 0; i < 5; i++ {
18
-		if err := system.Mount("", path, "", syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil && !os.IsNotExist(err) {
16
+		if err := syscall.Mount("", path, "", syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil && !os.IsNotExist(err) {
19 17
 			switch err {
20 18
 			case syscall.EINVAL:
21 19
 				// Probably not a mountpoint, use bind-mount
22
-				if err := system.Mount(path, path, "", syscall.MS_BIND, ""); err != nil {
20
+				if err := syscall.Mount(path, path, "", syscall.MS_BIND, ""); err != nil {
23 21
 					return err
24 22
 				}
25 23
 
26
-				return system.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC|defaultMountFlags, "")
24
+				return syscall.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC|defaultMountFlags, "")
27 25
 			case syscall.EBUSY:
28 26
 				time.Sleep(100 * time.Millisecond)
29 27
 				continue
... ...
@@ -47,7 +45,7 @@ func Restrict(mounts ...string) error {
47 47
 		}
48 48
 	}
49 49
 
50
-	if err := system.Mount("/dev/null", "/proc/kcore", "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) {
50
+	if err := syscall.Mount("/dev/null", "/proc/kcore", "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) {
51 51
 		return fmt.Errorf("unable to bind-mount /dev/null over /proc/kcore: %s", err)
52 52
 	}
53 53
 
... ...
@@ -5,8 +5,6 @@ import (
5 5
 	"crypto/rand"
6 6
 	"encoding/binary"
7 7
 	"fmt"
8
-	"github.com/dotcloud/docker/pkg/mount"
9
-	"github.com/dotcloud/docker/pkg/system"
10 8
 	"io"
11 9
 	"os"
12 10
 	"path/filepath"
... ...
@@ -14,6 +12,9 @@ import (
14 14
 	"strconv"
15 15
 	"strings"
16 16
 	"syscall"
17
+
18
+	"github.com/docker/libcontainer/system"
19
+	"github.com/dotcloud/docker/pkg/mount"
17 20
 )
18 21
 
19 22
 const (
... ...
@@ -153,16 +154,16 @@ func Getfilecon(path string) (string, error) {
153 153
 }
154 154
 
155 155
 func Setfscreatecon(scon string) error {
156
-	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon)
156
+	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), scon)
157 157
 }
158 158
 
159 159
 func Getfscreatecon() (string, error) {
160
-	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()))
160
+	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()))
161 161
 }
162 162
 
163 163
 // Return the SELinux label of the current process thread.
164 164
 func Getcon() (string, error) {
165
-	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid()))
165
+	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid()))
166 166
 }
167 167
 
168 168
 func Getpidcon(pid int) (string, error) {
... ...
@@ -192,7 +193,7 @@ func writeCon(name string, val string) error {
192 192
 }
193 193
 
194 194
 func Setexeccon(scon string) error {
195
-	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", system.Gettid()), scon)
195
+	return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), scon)
196 196
 }
197 197
 
198 198
 func (c SELinuxContext) Get() string {
199 199
new file mode 100644
... ...
@@ -0,0 +1,60 @@
0
+// +build linux
1
+
2
+package system
3
+
4
+import (
5
+	"os/exec"
6
+	"syscall"
7
+	"unsafe"
8
+)
9
+
10
+func Execv(cmd string, args []string, env []string) error {
11
+	name, err := exec.LookPath(cmd)
12
+	if err != nil {
13
+		return err
14
+	}
15
+
16
+	return syscall.Exec(name, args, env)
17
+}
18
+
19
+func ParentDeathSignal(sig uintptr) error {
20
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 {
21
+		return err
22
+	}
23
+	return nil
24
+}
25
+
26
+func GetParentDeathSignal() (int, error) {
27
+	var sig int
28
+
29
+	_, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0)
30
+
31
+	if err != 0 {
32
+		return -1, err
33
+	}
34
+
35
+	return sig, nil
36
+}
37
+
38
+func SetKeepCaps() error {
39
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 {
40
+		return err
41
+	}
42
+
43
+	return nil
44
+}
45
+
46
+func ClearKeepCaps() error {
47
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 {
48
+		return err
49
+	}
50
+
51
+	return nil
52
+}
53
+
54
+func Setctty() error {
55
+	if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
56
+		return err
57
+	}
58
+	return nil
59
+}
0 60
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+package system
1
+
2
+import (
3
+	"io/ioutil"
4
+	"path/filepath"
5
+	"strconv"
6
+	"strings"
7
+)
8
+
9
+// look in /proc to find the process start time so that we can verify
10
+// that this pid has started after ourself
11
+func GetProcessStartTime(pid int) (string, error) {
12
+	data, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat"))
13
+	if err != nil {
14
+		return "", err
15
+	}
16
+
17
+	parts := strings.Split(string(data), " ")
18
+	// the starttime is located at pos 22
19
+	// from the man page
20
+	//
21
+	// starttime %llu (was %lu before Linux 2.6)
22
+	// (22)  The  time the process started after system boot.  In kernels before Linux 2.6, this
23
+	// value was expressed in jiffies.  Since Linux 2.6, the value is expressed in  clock  ticks
24
+	// (divide by sysconf(_SC_CLK_TCK)).
25
+	return parts[22-1], nil // starts at 1
26
+}
0 27
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+package system
1
+
2
+import (
3
+	"fmt"
4
+	"runtime"
5
+	"syscall"
6
+)
7
+
8
+// Via http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7b21fddd087678a70ad64afc0f632e0f1071b092
9
+//
10
+// We need different setns values for the different platforms and arch
11
+// We are declaring the macro here because the SETNS syscall does not exist in th stdlib
12
+var setNsMap = map[string]uintptr{
13
+	"linux/amd64": 308,
14
+}
15
+
16
+func Setns(fd uintptr, flags uintptr) error {
17
+	ns, exists := setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)]
18
+	if !exists {
19
+		return fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime.GOARCH)
20
+	}
21
+
22
+	_, _, err := syscall.RawSyscall(ns, fd, flags, 0)
23
+	if err != 0 {
24
+		return err
25
+	}
26
+
27
+	return nil
28
+}
0 29
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+// +build linux,cgo
1
+
2
+package system
3
+
4
+/*
5
+#include <unistd.h>
6
+int get_hz(void) { return sysconf(_SC_CLK_TCK); }
7
+*/
8
+import "C"
9
+
10
+func GetClockTicks() int {
11
+	return int(C.get_hz())
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,59 @@
0
+package system
1
+
2
+import (
3
+	"syscall"
4
+	"unsafe"
5
+)
6
+
7
+// Returns a nil slice and nil error if the xattr is not set
8
+func Lgetxattr(path string, attr string) ([]byte, error) {
9
+	pathBytes, err := syscall.BytePtrFromString(path)
10
+	if err != nil {
11
+		return nil, err
12
+	}
13
+	attrBytes, err := syscall.BytePtrFromString(attr)
14
+	if err != nil {
15
+		return nil, err
16
+	}
17
+
18
+	dest := make([]byte, 128)
19
+	destBytes := unsafe.Pointer(&dest[0])
20
+	sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
21
+	if errno == syscall.ENODATA {
22
+		return nil, nil
23
+	}
24
+	if errno == syscall.ERANGE {
25
+		dest = make([]byte, sz)
26
+		destBytes := unsafe.Pointer(&dest[0])
27
+		sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
28
+	}
29
+	if errno != 0 {
30
+		return nil, errno
31
+	}
32
+
33
+	return dest[:sz], nil
34
+}
35
+
36
+var _zero uintptr
37
+
38
+func Lsetxattr(path string, attr string, data []byte, flags int) error {
39
+	pathBytes, err := syscall.BytePtrFromString(path)
40
+	if err != nil {
41
+		return err
42
+	}
43
+	attrBytes, err := syscall.BytePtrFromString(attr)
44
+	if err != nil {
45
+		return err
46
+	}
47
+	var dataBytes unsafe.Pointer
48
+	if len(data) > 0 {
49
+		dataBytes = unsafe.Pointer(&data[0])
50
+	} else {
51
+		dataBytes = unsafe.Pointer(&_zero)
52
+	}
53
+	_, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
54
+	if errno != 0 {
55
+		return errno
56
+	}
57
+	return nil
58
+}