| ... | ... |
@@ -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 |
| ... | ... |
@@ -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 | 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 |
+} |