瀏覽代碼

Merge pull request #8988 from crosbymichael/update-libcontainer-nov1

Update libcontainer to fd6df76562137aa3b18e44b790c
Michael Crosby 10 年之前
父節點
當前提交
68a25a5b74
共有 35 個文件被更改,包括 477 次插入363 次删除
  1. 1 7
      daemon/execdriver/native/init.go
  2. 2 8
      daemon/execdriver/native/utils.go
  3. 1 1
      hack/vendor.sh
  4. 88 0
      vendor/src/github.com/Sirupsen/logrus/formatter_bench_test.go
  5. 28 0
      vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md
  6. 54 0
      vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go
  7. 26 0
      vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go
  8. 9 0
      vendor/src/github.com/docker/libcontainer/.drone.yml
  9. 0 36
      vendor/src/github.com/docker/libcontainer/.travis.yml
  10. 0 1
      vendor/src/github.com/docker/libcontainer/MAINTAINERS
  11. 1 1
      vendor/src/github.com/docker/libcontainer/README.md
  12. 2 2
      vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go
  13. 15 8
      vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go
  14. 1 1
      vendor/src/github.com/docker/libcontainer/devices/devices.go
  15. 1 7
      vendor/src/github.com/docker/libcontainer/integration/init_test.go
  16. 12 0
      vendor/src/github.com/docker/libcontainer/label/label.go
  17. 13 2
      vendor/src/github.com/docker/libcontainer/label/label_selinux.go
  18. 42 1
      vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go
  19. 2 1
      vendor/src/github.com/docker/libcontainer/mount/init.go
  20. 38 55
      vendor/src/github.com/docker/libcontainer/namespaces/exec.go
  21. 16 12
      vendor/src/github.com/docker/libcontainer/namespaces/execin.go
  22. 18 6
      vendor/src/github.com/docker/libcontainer/namespaces/init.go
  23. 38 0
      vendor/src/github.com/docker/libcontainer/namespaces/utils.go
  24. 24 0
      vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go
  25. 2 2
      vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
  26. 8 0
      vendor/src/github.com/docker/libcontainer/network/network.go
  27. 3 0
      vendor/src/github.com/docker/libcontainer/network/veth.go
  28. 2 7
      vendor/src/github.com/docker/libcontainer/nsinit/init.go
  29. 3 7
      vendor/src/github.com/docker/libcontainer/nsinit/utils.go
  30. 25 0
      vendor/src/github.com/docker/libcontainer/selinux/selinux.go
  31. 1 1
      vendor/src/github.com/docker/libcontainer/selinux/selinux_test.go
  32. 0 105
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe.go
  33. 0 20
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_linux.go
  34. 0 72
      vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_test.go
  35. 1 0
      vendor/src/github.com/docker/libcontainer/system/syscall_linux_amd64.go

+ 1 - 7
daemon/execdriver/native/init.go

@@ -13,7 +13,6 @@ import (
 	"github.com/docker/docker/pkg/reexec"
 	"github.com/docker/libcontainer"
 	"github.com/docker/libcontainer/namespaces"
-	"github.com/docker/libcontainer/syncpipe"
 )
 
 func init() {
@@ -48,12 +47,7 @@ func initializer() {
 		writeError(err)
 	}
 
-	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, uintptr(*pipe))
-	if err != nil {
-		writeError(err)
-	}
-
-	if err := namespaces.Init(container, rootfs, *console, syncPipe, flag.Args()); err != nil {
+	if err := namespaces.Init(container, rootfs, *console, os.NewFile(uintptr(*pipe), "child"), flag.Args()); err != nil {
 		writeError(err)
 	}
 

+ 2 - 8
daemon/execdriver/native/utils.go

@@ -3,10 +3,10 @@
 package native
 
 import (
+	"encoding/json"
 	"os"
 
 	"github.com/docker/libcontainer"
-	"github.com/docker/libcontainer/syncpipe"
 )
 
 func findUserArgs() []string {
@@ -21,15 +21,9 @@ func findUserArgs() []string {
 // loadConfigFromFd loads a container's config from the sync pipe that is provided by
 // fd 3 when running a process
 func loadConfigFromFd() (*libcontainer.Config, error) {
-	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, 3)
-	if err != nil {
-		return nil, err
-	}
-
 	var config *libcontainer.Config
-	if err := syncPipe.ReadFromParent(&config); err != nil {
+	if err := json.NewDecoder(os.NewFile(3, "child")).Decode(&config); err != nil {
 		return nil, err
 	}
-
 	return config, nil
 }

+ 1 - 1
hack/vendor.sh

@@ -66,7 +66,7 @@ if [ "$1" = '--go' ]; then
 	mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
 fi
 
-clone git github.com/docker/libcontainer f60d7b9195f8dc0b5d343abbc3293da7c17bb11c
+clone git github.com/docker/libcontainer fd6df76562137aa3b18e44b790cb484fe2b6fa0b
 # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
 rm -rf src/github.com/docker/libcontainer/vendor
 eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')"

+ 88 - 0
vendor/src/github.com/Sirupsen/logrus/formatter_bench_test.go

@@ -0,0 +1,88 @@
+package logrus
+
+import (
+	"testing"
+	"time"
+)
+
+// smallFields is a small size data set for benchmarking
+var smallFields = Fields{
+	"foo":   "bar",
+	"baz":   "qux",
+	"one":   "two",
+	"three": "four",
+}
+
+// largeFields is a large size data set for benchmarking
+var largeFields = Fields{
+	"foo":       "bar",
+	"baz":       "qux",
+	"one":       "two",
+	"three":     "four",
+	"five":      "six",
+	"seven":     "eight",
+	"nine":      "ten",
+	"eleven":    "twelve",
+	"thirteen":  "fourteen",
+	"fifteen":   "sixteen",
+	"seventeen": "eighteen",
+	"nineteen":  "twenty",
+	"a":         "b",
+	"c":         "d",
+	"e":         "f",
+	"g":         "h",
+	"i":         "j",
+	"k":         "l",
+	"m":         "n",
+	"o":         "p",
+	"q":         "r",
+	"s":         "t",
+	"u":         "v",
+	"w":         "x",
+	"y":         "z",
+	"this":      "will",
+	"make":      "thirty",
+	"entries":   "yeah",
+}
+
+func BenchmarkSmallTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
+}
+
+func BenchmarkLargeTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
+}
+
+func BenchmarkSmallColoredTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
+}
+
+func BenchmarkLargeColoredTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
+}
+
+func BenchmarkSmallJSONFormatter(b *testing.B) {
+	doBenchmark(b, &JSONFormatter{}, smallFields)
+}
+
+func BenchmarkLargeJSONFormatter(b *testing.B) {
+	doBenchmark(b, &JSONFormatter{}, largeFields)
+}
+
+func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
+	entry := &Entry{
+		Time:    time.Time{},
+		Level:   InfoLevel,
+		Message: "message",
+		Data:    fields,
+	}
+	var d []byte
+	var err error
+	for i := 0; i < b.N; i++ {
+		d, err = formatter.Format(entry)
+		if err != nil {
+			b.Fatal(err)
+		}
+		b.SetBytes(int64(len(d)))
+	}
+}

+ 28 - 0
vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md

@@ -0,0 +1,28 @@
+# Papertrail Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" />
+
+[Papertrail](https://papertrailapp.com) provides hosted log management. Once stored in Papertrail, you can [group](http://help.papertrailapp.com/kb/how-it-works/groups/) your logs on various dimensions, [search](http://help.papertrailapp.com/kb/how-it-works/search-syntax) them, and trigger [alerts](http://help.papertrailapp.com/kb/how-it-works/alerts).
+
+In most deployments, you'll want to send logs to Papertrail via their [remote_syslog](http://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-text-log-files-in-unix/) daemon, which requires no application-specific configuration. This hook is intended for relatively low-volume logging, likely in managed cloud hosting deployments where installing `remote_syslog` is not possible.
+
+## Usage
+
+You can find your Papertrail UDP port on your [Papertrail account page](https://papertrailapp.com/account/destinations). Substitute it below for `YOUR_PAPERTRAIL_UDP_PORT`.
+
+For `YOUR_APP_NAME`, substitute a short string that will readily identify your application or service in the logs.
+
+```go
+import (
+  "log/syslog"
+  "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/papertrail"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := logrus_papertrail.NewPapertrailHook("logs.papertrailapp.com", YOUR_PAPERTRAIL_UDP_PORT, YOUR_APP_NAME)
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```

+ 54 - 0
vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go

@@ -0,0 +1,54 @@
+package logrus_papertrail
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+)
+
+const (
+	format = "Jan 2 15:04:05"
+)
+
+// PapertrailHook to send logs to a logging service compatible with the Papertrail API.
+type PapertrailHook struct {
+	Host    string
+	Port    int
+	AppName string
+	UDPConn net.Conn
+}
+
+// NewPapertrailHook creates a hook to be added to an instance of logger.
+func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) {
+	conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port))
+	return &PapertrailHook{host, port, appName, conn}, err
+}
+
+// Fire is called when a log event is fired.
+func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
+	date := time.Now().Format(format)
+	payload := fmt.Sprintf("<22> %s %s: [%s] %s", date, hook.AppName, entry.Data["level"], entry.Message)
+
+	bytesWritten, err := hook.UDPConn.Write([]byte(payload))
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP. Wrote %d bytes before error: %v", bytesWritten, err)
+		return err
+	}
+
+	return nil
+}
+
+// Levels returns the available logging levels.
+func (hook *PapertrailHook) Levels() []logrus.Level {
+	return []logrus.Level{
+		logrus.PanicLevel,
+		logrus.FatalLevel,
+		logrus.ErrorLevel,
+		logrus.WarnLevel,
+		logrus.InfoLevel,
+		logrus.DebugLevel,
+	}
+}

+ 26 - 0
vendor/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go

@@ -0,0 +1,26 @@
+package logrus_papertrail
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/stvp/go-udp-testing"
+)
+
+func TestWritingToUDP(t *testing.T) {
+	port := 16661
+	udp.SetAddr(fmt.Sprintf(":%d", port))
+
+	hook, err := NewPapertrailHook("localhost", port, "test")
+	if err != nil {
+		t.Errorf("Unable to connect to local UDP server.")
+	}
+
+	log := logrus.New()
+	log.Hooks.Add(hook)
+
+	udp.ShouldReceive(t, "foo", func() {
+		log.Info("foo")
+	})
+}

+ 9 - 0
vendor/src/github.com/docker/libcontainer/.drone.yml

@@ -0,0 +1,9 @@
+image: dockercore/libcontainer
+script:
+# Setup the DockerInDocker environment.
+  - /dind
+  - sed -i 's!docker/docker!docker/libcontainer!' /go/src/github.com/docker/docker/hack/make/.validate
+  - bash /go/src/github.com/docker/docker/hack/make/validate-dco
+  - bash /go/src/github.com/docker/docker/hack/make/validate-gofmt
+  - export GOPATH="$GOPATH:/go:$(pwd)/vendor" # Drone mucks with our GOPATH
+  - make direct-test

+ 0 - 36
vendor/src/github.com/docker/libcontainer/.travis.yml

@@ -1,36 +0,0 @@
-language: go
-go: 1.3
-
-# let us have pretty experimental Docker-based Travis workers
-sudo: false
-
-env:
-    - TRAVIS_GLOBAL_WTF=1
-    - _GOOS=linux _GOARCH=amd64 CGO_ENABLED=1
-    - _GOOS=linux _GOARCH=amd64 CGO_ENABLED=0
-#    - _GOOS=linux _GOARCH=386 CGO_ENABLED=1 # TODO add this once Travis can handle it (https://github.com/travis-ci/travis-ci/issues/2207#issuecomment-49625061)
-    - _GOOS=linux _GOARCH=386 CGO_ENABLED=0
-    - _GOOS=linux _GOARCH=arm CGO_ENABLED=0
-
-install:
-    - go get code.google.com/p/go.tools/cmd/cover
-    - mkdir -pv "${GOPATH%%:*}/src/github.com/docker" && [ -d "${GOPATH%%:*}/src/github.com/docker/libcontainer" ] || ln -sv "$(readlink -f .)" "${GOPATH%%:*}/src/github.com/docker/libcontainer"
-    - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then
-          gvm cross "$_GOOS" "$_GOARCH";
-          export GOOS="$_GOOS" GOARCH="$_GOARCH";
-      fi
-    - export GOPATH="$GOPATH:$(pwd)/vendor"
-    - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then go env; fi
-    - go get -d -v ./... # TODO remove this if /docker/docker gets purged from our includes
-    - if [ "$TRAVIS_GLOBAL_WTF" ]; then
-          export DOCKER_PATH="${GOPATH%%:*}/src/github.com/docker/docker";
-          mkdir -p "$DOCKER_PATH/hack/make";
-          ( cd "$DOCKER_PATH/hack/make" && wget -c 'https://raw.githubusercontent.com/docker/docker/master/hack/make/'{.validate,validate-dco,validate-gofmt} );
-          sed -i 's!docker/docker!docker/libcontainer!' "$DOCKER_PATH/hack/make/.validate";
-      fi
-
-script:
-    - if [ "$TRAVIS_GLOBAL_WTF" ]; then bash "$DOCKER_PATH/hack/make/validate-dco"; fi
-    - if [ "$TRAVIS_GLOBAL_WTF" ]; then bash "$DOCKER_PATH/hack/make/validate-gofmt"; fi
-    - if [ -z "$TRAVIS_GLOBAL_WTF" ]; then make direct-build; fi
-    - if [ -z "$TRAVIS_GLOBAL_WTF" -a "$GOARCH" != 'arm' ]; then make direct-test-short; fi

+ 0 - 1
vendor/src/github.com/docker/libcontainer/MAINTAINERS

@@ -2,5 +2,4 @@ Michael Crosby <michael@docker.com> (@crosbymichael)
 Rohit Jnagal <jnagal@google.com> (@rjnagal)
 Victor Marmol <vmarmol@google.com> (@vmarmol)
 Mrunal Patel <mpatel@redhat.com> (@mrunalp)
-.travis.yml: Tianon Gravi <admwiggin@gmail.com> (@tianon)
 update-vendor.sh: Tianon Gravi <admwiggin@gmail.com> (@tianon)

+ 1 - 1
vendor/src/github.com/docker/libcontainer/README.md

@@ -1,4 +1,4 @@
-## libcontainer - reference implementation for containers [![Build Status](https://travis-ci.org/docker/libcontainer.png?branch=master)](https://travis-ci.org/docker/libcontainer)
+## libcontainer - reference implementation for containers [![Build Status](https://ci.dockerproject.com/github.com/docker/libcontainer/status.svg?branch=master)](https://ci.dockerproject.com/github.com/docker/libcontainer) 
 
 ### Note on API changes:
 

+ 2 - 2
vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go

@@ -57,7 +57,7 @@ func TestGetCgroupParamsInt(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	} else if value != 0 {
-		t.Fatalf("Expected %d to equal %f", value, 0)
+		t.Fatalf("Expected %d to equal %d", value, 0)
 	}
 
 	// Success with negative values lesser than min int64
@@ -70,7 +70,7 @@ func TestGetCgroupParamsInt(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	} else if value != 0 {
-		t.Fatalf("Expected %d to equal %f", value, 0)
+		t.Fatalf("Expected %d to equal %d", value, 0)
 	}
 
 	// Not a float.

+ 15 - 8
vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go

@@ -43,6 +43,13 @@ var (
 	}
 )
 
+func newProp(name string, units interface{}) systemd.Property {
+	return systemd.Property{
+		Name:  name,
+		Value: dbus.MakeVariant(units),
+	}
+}
+
 func UseSystemd() bool {
 	s, err := os.Stat("/run/systemd/system")
 	if err != nil || !s.IsDir() {
@@ -99,27 +106,27 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
 	}
 
 	properties = append(properties,
-		systemd.Property{"Slice", dbus.MakeVariant(slice)},
-		systemd.Property{"Description", dbus.MakeVariant("docker container " + c.Name)},
-		systemd.Property{"PIDs", dbus.MakeVariant([]uint32{uint32(pid)})},
+		systemd.PropSlice(slice),
+		systemd.PropDescription("docker container "+c.Name),
+		newProp("PIDs", []uint32{uint32(pid)}),
 	)
 
 	// Always enable accounting, this gets us the same behaviour as the fs implementation,
 	// plus the kernel has some problems with joining the memory cgroup at a later time.
 	properties = append(properties,
-		systemd.Property{"MemoryAccounting", dbus.MakeVariant(true)},
-		systemd.Property{"CPUAccounting", dbus.MakeVariant(true)},
-		systemd.Property{"BlockIOAccounting", dbus.MakeVariant(true)})
+		newProp("MemoryAccounting", true),
+		newProp("CPUAccounting", true),
+		newProp("BlockIOAccounting", true))
 
 	if c.Memory != 0 {
 		properties = append(properties,
-			systemd.Property{"MemoryLimit", dbus.MakeVariant(uint64(c.Memory))})
+			newProp("MemoryLimit", uint64(c.Memory)))
 	}
 	// TODO: MemoryReservation and MemorySwap not available in systemd
 
 	if c.CpuShares != 0 {
 		properties = append(properties,
-			systemd.Property{"CPUShares", dbus.MakeVariant(uint64(c.CpuShares))})
+			newProp("CPUShares", uint64(c.CpuShares)))
 	}
 
 	if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {

+ 1 - 1
vendor/src/github.com/docker/libcontainer/devices/devices.go

@@ -103,7 +103,7 @@ func getDeviceNodes(path string) ([]*Device, error) {
 		switch {
 		case f.IsDir():
 			switch f.Name() {
-			case "pts", "shm", "fd":
+			case "pts", "shm", "fd", "mqueue":
 				continue
 			default:
 				sub, err := getDeviceNodes(filepath.Join(path, f.Name()))

+ 1 - 7
vendor/src/github.com/docker/libcontainer/integration/init_test.go

@@ -6,7 +6,6 @@ import (
 	"runtime"
 
 	"github.com/docker/libcontainer/namespaces"
-	"github.com/docker/libcontainer/syncpipe"
 )
 
 // init runs the libcontainer initialization code because of the busybox style needs
@@ -27,12 +26,7 @@ func init() {
 		log.Fatal(err)
 	}
 
-	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, 3)
-	if err != nil {
-		log.Fatalf("unable to create sync pipe: %s", err)
-	}
-
-	if err := namespaces.Init(container, rootfs, "", syncPipe, os.Args[3:]); err != nil {
+	if err := namespaces.Init(container, rootfs, "", os.NewFile(3, "pipe"), os.Args[3:]); err != nil {
 		log.Fatalf("unable to initialize for container: %s", err)
 	}
 	os.Exit(1)

+ 12 - 0
vendor/src/github.com/docker/libcontainer/label/label.go

@@ -43,3 +43,15 @@ func ReserveLabel(label string) error {
 func UnreserveLabel(label string) error {
 	return nil
 }
+
+// DupSecOpt takes an process label and returns security options that
+// can be used to set duplicate labels on future container processes
+func DupSecOpt(src string) []string {
+	return nil
+}
+
+// DisableSecOpt returns a security opt that can disable labeling
+// support for future container processes
+func DisableSecOpt() []string {
+	return nil
+}

+ 13 - 2
vendor/src/github.com/docker/libcontainer/label/label_selinux.go

@@ -17,7 +17,6 @@ func InitLabels(options []string) (string, string, error) {
 	if !selinux.SelinuxEnabled() {
 		return "", "", nil
 	}
-	var err error
 	processLabel, mountLabel := selinux.GetLxcContexts()
 	if processLabel != "" {
 		pcon := selinux.NewContext(processLabel)
@@ -38,7 +37,7 @@ func InitLabels(options []string) (string, string, error) {
 		processLabel = pcon.Get()
 		mountLabel = mcon.Get()
 	}
-	return processLabel, mountLabel, err
+	return processLabel, mountLabel, nil
 }
 
 // DEPRECATED: The GenLabels function is only to be used during the transition to the official API.
@@ -130,3 +129,15 @@ func UnreserveLabel(label string) error {
 	selinux.FreeLxcContexts(label)
 	return nil
 }
+
+// DupSecOpt takes an process label and returns security options that
+// can be used to set duplicate labels on future container processes
+func DupSecOpt(src string) []string {
+	return selinux.DupSecOpt(src)
+}
+
+// DisableSecOpt returns a security opt that can disable labeling
+// support for future container processes
+func DisableSecOpt() []string {
+	return selinux.DisableSecOpt()
+}

+ 42 - 1
vendor/src/github.com/docker/libcontainer/label/label_selinux_test.go

@@ -3,6 +3,7 @@
 package label
 
 import (
+	"strings"
 	"testing"
 
 	"github.com/docker/libcontainer/selinux"
@@ -33,7 +34,7 @@ func TestInit(t *testing.T) {
 			t.Fatal(err)
 		}
 		if plabel != "user_u:user_r:user_t:s0:c1,c15" || mlabel != "user_u:object_r:svirt_sandbox_file_t:s0:c1,c15" {
-			t.Log("InitLabels User Failed")
+			t.Log("InitLabels User Match Failed")
 			t.Log(plabel, mlabel)
 			t.Fatal(err)
 		}
@@ -46,3 +47,43 @@ func TestInit(t *testing.T) {
 		}
 	}
 }
+func TestDuplicateLabel(t *testing.T) {
+	secopt := DupSecOpt("system_u:system_r:svirt_lxc_net_t:s0:c1,c2")
+	t.Log(secopt)
+	for _, opt := range secopt {
+		con := strings.SplitN(opt, ":", 3)
+		if len(con) != 3 || con[0] != "label" {
+			t.Errorf("Invalid DupSecOpt return value")
+			continue
+		}
+		if con[1] == "user" {
+			if con[2] != "system_u" {
+				t.Errorf("DupSecOpt Failed user incorrect")
+			}
+			continue
+		}
+		if con[1] == "role" {
+			if con[2] != "system_r" {
+				t.Errorf("DupSecOpt Failed role incorrect")
+			}
+			continue
+		}
+		if con[1] == "type" {
+			if con[2] != "svirt_lxc_net_t" {
+				t.Errorf("DupSecOpt Failed type incorrect")
+			}
+			continue
+		}
+		if con[1] == "level" {
+			if con[2] != "s0:c1,c2" {
+				t.Errorf("DupSecOpt Failed level incorrect")
+			}
+			continue
+		}
+		t.Errorf("DupSecOpt Failed invalid field %q", con[1])
+	}
+	secopt = DisableSecOpt()
+	if secopt[0] != "label:disable" {
+		t.Errorf("DisableSecOpt Failed level incorrect")
+	}
+}

+ 2 - 1
vendor/src/github.com/docker/libcontainer/mount/init.go

@@ -97,7 +97,7 @@ func InitializeMountNamespace(rootfs, console string, sysReadonly bool, mountCon
 	return nil
 }
 
-// mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts
+// mountSystem sets up linux specific system mounts like mqueue, sys, proc, shm, and devpts
 // inside the mount namespace
 func mountSystem(rootfs string, sysReadonly bool, mountConfig *MountConfig) error {
 	for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, sysReadonly) {
@@ -168,6 +168,7 @@ func newSystemMounts(rootfs, mountLabel string, sysReadonly bool) []mount {
 		{source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags},
 		{source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: label.FormatMountLabel("mode=755", mountLabel)},
 		{source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)},
+		{source: "mqueue", path: filepath.Join(rootfs, "dev", "mqueue"), device: "mqueue", flags: defaultMountFlags},
 		{source: "devpts", path: filepath.Join(rootfs, "dev", "pts"), device: "devpts", flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, data: label.FormatMountLabel("newinstance,ptmxmode=0666,mode=620,gid=5", mountLabel)},
 	}
 

+ 38 - 55
vendor/src/github.com/docker/libcontainer/namespaces/exec.go

@@ -3,6 +3,7 @@
 package namespaces
 
 import (
+	"encoding/json"
 	"io"
 	"os"
 	"os/exec"
@@ -13,7 +14,6 @@ import (
 	"github.com/docker/libcontainer/cgroups/fs"
 	"github.com/docker/libcontainer/cgroups/systemd"
 	"github.com/docker/libcontainer/network"
-	"github.com/docker/libcontainer/syncpipe"
 	"github.com/docker/libcontainer/system"
 )
 
@@ -22,19 +22,17 @@ import (
 // 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, stdin io.Reader, stdout, stderr io.Writer, console, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
-	var (
-		err error
-	)
+	var err error
 
 	// create a pipe so that we can syncronize with the namespaced process and
-	// pass the veth name to the child
-	syncPipe, err := syncpipe.NewSyncPipe()
+	// pass the state and configuration to the child process
+	parent, child, err := newInitPipe()
 	if err != nil {
 		return -1, err
 	}
-	defer syncPipe.Close()
+	defer parent.Close()
 
-	command := createCommand(container, console, dataPath, os.Args[0], syncPipe.Child(), args)
+	command := createCommand(container, console, dataPath, os.Args[0], child, args)
 	// 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
@@ -43,39 +41,47 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
 	command.Stderr = stderr
 
 	if err := command.Start(); err != nil {
+		child.Close()
 		return -1, err
 	}
+	child.Close()
 
-	// Now we passed the pipe to the child, close our side
-	syncPipe.CloseChild()
+	terminate := func(terr error) (int, error) {
+		// TODO: log the errors for kill and wait
+		command.Process.Kill()
+		command.Wait()
+		return -1, terr
+	}
 
 	started, err := system.GetProcessStartTime(command.Process.Pid)
 	if err != nil {
-		return -1, err
+		return terminate(err)
 	}
 
 	// Do this before syncing with child so that no children
 	// can escape the cgroup
 	cgroupRef, err := SetupCgroups(container, command.Process.Pid)
 	if err != nil {
-		command.Process.Kill()
-		command.Wait()
-		return -1, err
+		return terminate(err)
 	}
 	defer cgroupRef.Cleanup()
 
 	cgroupPaths, err := cgroupRef.Paths()
 	if err != nil {
-		command.Process.Kill()
-		command.Wait()
-		return -1, err
+		return terminate(err)
 	}
 
 	var networkState network.NetworkState
-	if err := InitializeNetworking(container, command.Process.Pid, syncPipe, &networkState); err != nil {
-		command.Process.Kill()
-		command.Wait()
-		return -1, err
+	if err := InitializeNetworking(container, command.Process.Pid, &networkState); err != nil {
+		return terminate(err)
+	}
+	// send the state to the container's init process then shutdown writes for the parent
+	if err := json.NewEncoder(parent).Encode(networkState); err != nil {
+		return terminate(err)
+	}
+	// shutdown writes for the parent side of the pipe
+	if err := syscall.Shutdown(int(parent.Fd()), syscall.SHUT_WR); err != nil {
+		return terminate(err)
 	}
 
 	state := &libcontainer.State{
@@ -86,17 +92,18 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
 	}
 
 	if err := libcontainer.SaveState(dataPath, state); err != nil {
-		command.Process.Kill()
-		command.Wait()
-		return -1, err
+		return terminate(err)
 	}
 	defer libcontainer.DeleteState(dataPath)
 
-	// Sync with child
-	if err := syncPipe.ReadFromChild(); err != nil {
-		command.Process.Kill()
-		command.Wait()
-		return -1, err
+	// wait for the child process to fully complete and receive an error message
+	// if one was encoutered
+	var ierr *initError
+	if err := json.NewDecoder(parent).Decode(&ierr); err != nil && err != io.EOF {
+		return terminate(err)
+	}
+	if ierr != nil {
+		return terminate(ierr)
 	}
 
 	if startCallback != nil {
@@ -108,7 +115,6 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
 			return -1, err
 		}
 	}
-
 	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
 }
 
@@ -129,16 +135,6 @@ func DefaultCreateCommand(container *libcontainer.Config, console, dataPath, ini
 		"data_path=" + dataPath,
 	}
 
-	/*
-	   TODO: move user and wd into env
-	   if user != "" {
-	       env = append(env, "user="+user)
-	   }
-	   if workingDir != "" {
-	       env = append(env, "wd="+workingDir)
-	   }
-	*/
-
 	command := exec.Command(init, append([]string{"init", "--"}, args...)...)
 	// make sure the process is executed inside the context of the rootfs
 	command.Dir = container.RootFs
@@ -173,7 +169,7 @@ func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgro
 
 // InitializeNetworking creates the container's network stack outside of the namespace and moves
 // interfaces into the container's net namespaces if necessary
-func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *syncpipe.SyncPipe, networkState *network.NetworkState) error {
+func InitializeNetworking(container *libcontainer.Config, nspid int, networkState *network.NetworkState) error {
 	for _, config := range container.Networks {
 		strategy, err := network.GetStrategy(config.Type)
 		if err != nil {
@@ -183,18 +179,5 @@ func InitializeNetworking(container *libcontainer.Config, nspid int, pipe *syncp
 			return err
 		}
 	}
-	return pipe.SendToChild(networkState)
-}
-
-// GetNamespaceFlags parses the container's Namespaces options to set the correct
-// flags on clone, unshare, and setns
-func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
-	for key, enabled := range namespaces {
-		if enabled {
-			if ns := GetNamespace(key); ns != nil {
-				flag |= ns.Value
-			}
-		}
-	}
-	return flag
+	return nil
 }

+ 16 - 12
vendor/src/github.com/docker/libcontainer/namespaces/execin.go

@@ -3,6 +3,7 @@
 package namespaces
 
 import (
+	"encoding/json"
 	"fmt"
 	"io"
 	"os"
@@ -15,7 +16,6 @@ import (
 	"github.com/docker/libcontainer/apparmor"
 	"github.com/docker/libcontainer/cgroups"
 	"github.com/docker/libcontainer/label"
-	"github.com/docker/libcontainer/syncpipe"
 	"github.com/docker/libcontainer/system"
 )
 
@@ -41,11 +41,11 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs
 		}
 	}
 
-	pipe, err := syncpipe.NewSyncPipe()
+	parent, child, err := newInitPipe()
 	if err != nil {
 		return -1, err
 	}
-	defer pipe.Close()
+	defer parent.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
@@ -53,23 +53,28 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs
 	cmd.Stdin = stdin
 	cmd.Stdout = stdout
 	cmd.Stderr = stderr
-
-	cmd.ExtraFiles = []*os.File{pipe.Child()}
+	cmd.ExtraFiles = []*os.File{child}
 
 	if err := cmd.Start(); err != nil {
+		child.Close()
 		return -1, err
 	}
-	pipe.CloseChild()
+	child.Close()
+
+	terminate := func(terr error) (int, error) {
+		// TODO: log the errors for kill and wait
+		cmd.Process.Kill()
+		cmd.Wait()
+		return -1, terr
+	}
 
 	// Enter cgroups.
 	if err := EnterCgroups(state, cmd.Process.Pid); err != nil {
-		return -1, err
+		return terminate(err)
 	}
 
-	if err := pipe.SendToChild(container); err != nil {
-		cmd.Process.Kill()
-		cmd.Wait()
-		return -1, err
+	if err := json.NewEncoder(parent).Encode(container); err != nil {
+		return terminate(err)
 	}
 
 	if startCallback != nil {
@@ -81,7 +86,6 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs
 			return -1, err
 		}
 	}
-
 	return cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
 }
 

+ 18 - 6
vendor/src/github.com/docker/libcontainer/namespaces/init.go

@@ -3,7 +3,9 @@
 package namespaces
 
 import (
+	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"strings"
 	"syscall"
@@ -18,7 +20,6 @@ import (
 	"github.com/docker/libcontainer/network"
 	"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/user"
 	"github.com/docker/libcontainer/utils"
@@ -30,11 +31,22 @@ import (
 // and other options required for the new container.
 // The caller of Init function has to ensure that the go runtime is locked to an OS thread
 // (using runtime.LockOSThread) else system calls like setns called within Init may not work as intended.
-func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *syncpipe.SyncPipe, args []string) (err error) {
+func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, pipe *os.File, args []string) (err error) {
 	defer func() {
+		// if we have an error during the initialization of the container's init then send it back to the
+		// parent process in the form of an initError.
 		if err != nil {
-			syncPipe.ReportChildError(err)
+			// ensure that any data sent from the parent is consumed so it doesn't
+			// receive ECONNRESET when the child writes to the pipe.
+			ioutil.ReadAll(pipe)
+			if err := json.NewEncoder(pipe).Encode(initError{
+				Message: err.Error(),
+			}); err != nil {
+				panic(err)
+			}
 		}
+		// ensure that this pipe is always closed
+		pipe.Close()
 	}()
 
 	rootfs, err := utils.ResolveRootfs(uncleanRootfs)
@@ -50,7 +62,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn
 
 	// We always read this as it is a way to sync with the parent as well
 	var networkState *network.NetworkState
-	if err := syncPipe.ReadFromParent(&networkState); err != nil {
+	if err := json.NewDecoder(pipe).Decode(&networkState); err != nil {
 		return err
 	}
 
@@ -164,11 +176,11 @@ func SetupUser(u string) error {
 		return fmt.Errorf("setgroups %s", err)
 	}
 
-	if err := syscall.Setgid(gid); err != nil {
+	if err := system.Setgid(gid); err != nil {
 		return fmt.Errorf("setgid %s", err)
 	}
 
-	if err := syscall.Setuid(uid); err != nil {
+	if err := system.Setuid(uid); err != nil {
 		return fmt.Errorf("setuid %s", err)
 	}
 

+ 38 - 0
vendor/src/github.com/docker/libcontainer/namespaces/utils.go

@@ -0,0 +1,38 @@
+// +build linux
+
+package namespaces
+
+import (
+	"os"
+	"syscall"
+)
+
+type initError struct {
+	Message string `json:"message,omitempty"`
+}
+
+func (i initError) Error() string {
+	return i.Message
+}
+
+// New returns a newly initialized Pipe for communication between processes
+func newInitPipe() (parent *os.File, child *os.File, err error) {
+	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
+	if err != nil {
+		return nil, nil, err
+	}
+	return os.NewFile(uintptr(fds[1]), "parent"), os.NewFile(uintptr(fds[0]), "child"), nil
+}
+
+// GetNamespaceFlags parses the container's Namespaces options to set the correct
+// flags on clone, unshare, and setns
+func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
+	for key, enabled := range namespaces {
+		if enabled {
+			if ns := GetNamespace(key); ns != nil {
+				flag |= ns.Value
+			}
+		}
+	}
+	return flag
+}

+ 24 - 0
vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go

@@ -7,6 +7,7 @@ import (
 	"math/rand"
 	"net"
 	"os"
+	"path/filepath"
 	"sync/atomic"
 	"syscall"
 	"unsafe"
@@ -1204,6 +1205,28 @@ func SetMacAddress(name, addr string) error {
 	return nil
 }
 
+func SetHairpinMode(iface *net.Interface, enabled bool) error {
+	sysPath := filepath.Join("/sys/class/net", iface.Name, "brport/hairpin_mode")
+
+	sysFile, err := os.OpenFile(sysPath, os.O_WRONLY, 0)
+	if err != nil {
+		return err
+	}
+	defer sysFile.Close()
+
+	var writeVal []byte
+	if enabled {
+		writeVal = []byte("1")
+	} else {
+		writeVal = []byte("0")
+	}
+	if _, err := sysFile.Write(writeVal); err != nil {
+		return err
+	}
+
+	return nil
+}
+
 func ChangeName(iface *net.Interface, newName string) error {
 	if len(newName) >= IFNAMSIZ {
 		return fmt.Errorf("Interface name %s too long", newName)
@@ -1224,5 +1247,6 @@ func ChangeName(iface *net.Interface, newName string) error {
 	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 {
 		return errno
 	}
+
 	return nil
 }

+ 2 - 2
vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go

@@ -116,7 +116,7 @@ func TestNetworkSetMacAddress(t *testing.T) {
 	ifcBeforeSet := readLink(t, tl.name)
 
 	if err := NetworkSetMacAddress(ifcBeforeSet, macaddr); err != nil {
-		t.Fatalf("Could not set %s MAC address on %#v interface: err", macaddr, tl, err)
+		t.Fatalf("Could not set %s MAC address on %#v interface: %s", macaddr, tl, err)
 	}
 
 	ifcAfterSet := readLink(t, tl.name)
@@ -140,7 +140,7 @@ func TestNetworkSetMTU(t *testing.T) {
 	ifcBeforeSet := readLink(t, tl.name)
 
 	if err := NetworkSetMTU(ifcBeforeSet, mtu); err != nil {
-		t.Fatalf("Could not set %d MTU on %#v interface: err", mtu, tl, err)
+		t.Fatalf("Could not set %d MTU on %#v interface: %s", mtu, tl, err)
 	}
 
 	ifcAfterSet := readLink(t, tl.name)

+ 8 - 0
vendor/src/github.com/docker/libcontainer/network/network.go

@@ -95,3 +95,11 @@ func SetMtu(name string, mtu int) error {
 	}
 	return netlink.NetworkSetMTU(iface, mtu)
 }
+
+func SetHairpinMode(name string, enabled bool) error {
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		return err
+	}
+	return netlink.SetHairpinMode(iface, enabled)
+}

+ 3 - 0
vendor/src/github.com/docker/libcontainer/network/veth.go

@@ -39,6 +39,9 @@ func (v *Veth) Create(n *Network, nspid int, networkState *NetworkState) error {
 	if err := SetMtu(name1, n.Mtu); err != nil {
 		return err
 	}
+	if err := SetHairpinMode(name1, true); err != nil {
+		return err
+	}
 	if err := InterfaceUp(name1); err != nil {
 		return err
 	}

+ 2 - 7
vendor/src/github.com/docker/libcontainer/nsinit/init.go

@@ -8,7 +8,6 @@ import (
 
 	"github.com/codegangsta/cli"
 	"github.com/docker/libcontainer/namespaces"
-	"github.com/docker/libcontainer/syncpipe"
 )
 
 var (
@@ -41,12 +40,8 @@ func initAction(context *cli.Context) {
 		log.Fatal(err)
 	}
 
-	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, uintptr(pipeFd))
-	if err != nil {
-		log.Fatalf("unable to create sync pipe: %s", err)
-	}
-
-	if err := namespaces.Init(container, rootfs, console, syncPipe, []string(context.Args())); err != nil {
+	pipe := os.NewFile(uintptr(pipeFd), "pipe")
+	if err := namespaces.Init(container, rootfs, console, pipe, []string(context.Args())); err != nil {
 		log.Fatalf("unable to initialize for container: %s", err)
 	}
 }

+ 3 - 7
vendor/src/github.com/docker/libcontainer/nsinit/utils.go

@@ -8,7 +8,6 @@ import (
 
 	"github.com/codegangsta/cli"
 	"github.com/docker/libcontainer"
-	"github.com/docker/libcontainer/syncpipe"
 )
 
 // rFunc is a function registration for calling after an execin
@@ -59,16 +58,13 @@ func findUserArgs() []string {
 // loadConfigFromFd loads a container's config from the sync pipe that is provided by
 // fd 3 when running a process
 func loadConfigFromFd() (*libcontainer.Config, error) {
-	syncPipe, err := syncpipe.NewSyncPipeFromFd(0, 3)
-	if err != nil {
-		return nil, err
-	}
+	pipe := os.NewFile(3, "pipe")
+	defer pipe.Close()
 
 	var config *libcontainer.Config
-	if err := syncPipe.ReadFromParent(&config); err != nil {
+	if err := json.NewDecoder(pipe).Decode(&config); err != nil {
 		return nil, err
 	}
-
 	return config, nil
 }
 

+ 25 - 0
vendor/src/github.com/docker/libcontainer/selinux/selinux.go

@@ -434,3 +434,28 @@ func Chcon(fpath string, scon string, recurse bool) error {
 
 	return Setfilecon(fpath, scon)
 }
+
+// DupSecOpt takes an SELinux process label and returns security options that
+// can will set the SELinux Type and Level for future container processes
+func DupSecOpt(src string) []string {
+	if src == "" {
+		return nil
+	}
+	con := NewContext(src)
+	if con["user"] == "" ||
+		con["role"] == "" ||
+		con["type"] == "" ||
+		con["level"] == "" {
+		return nil
+	}
+	return []string{"label:user:" + con["user"],
+		"label:role:" + con["role"],
+		"label:type:" + con["type"],
+		"label:level:" + con["level"]}
+}
+
+// DisableSecOpt returns a security opt that can be used to disabling SELinux
+// labeling support for future container processes
+func DisableSecOpt() []string {
+	return []string{"label:disable"}
+}

+ 1 - 1
vendor/src/github.com/docker/libcontainer/selinux/selinux_test.go

@@ -42,7 +42,7 @@ func TestSELinux(t *testing.T) {
 		t.Log("getenforce ", selinux.SelinuxGetEnforce())
 		t.Log("getenforcemode ", selinux.SelinuxGetEnforceMode())
 		pid := os.Getpid()
-		t.Log("PID:%d MCS:%s\n", pid, selinux.IntToMcs(pid, 1023))
+		t.Logf("PID:%d MCS:%s\n", pid, selinux.IntToMcs(pid, 1023))
 		err = selinux.Setfscreatecon("unconfined_u:unconfined_r:unconfined_t:s0")
 		if err == nil {
 			t.Log(selinux.Getfscreatecon())

+ 0 - 105
vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe.go

@@ -1,105 +0,0 @@
-package syncpipe
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"syscall"
-)
-
-// SyncPipe allows communication to and from the child processes
-// to it's parent and allows the two independent processes to
-// syncronize their state.
-type SyncPipe struct {
-	parent, child *os.File
-}
-
-func NewSyncPipeFromFd(parentFd, childFd uintptr) (*SyncPipe, error) {
-	s := &SyncPipe{}
-
-	if parentFd > 0 {
-		s.parent = os.NewFile(parentFd, "parentPipe")
-	} else if childFd > 0 {
-		s.child = os.NewFile(childFd, "childPipe")
-	} else {
-		return nil, fmt.Errorf("no valid sync pipe fd specified")
-	}
-
-	return s, nil
-}
-
-func (s *SyncPipe) Child() *os.File {
-	return s.child
-}
-
-func (s *SyncPipe) Parent() *os.File {
-	return s.parent
-}
-
-func (s *SyncPipe) SendToChild(v interface{}) error {
-	data, err := json.Marshal(v)
-	if err != nil {
-		return err
-	}
-
-	s.parent.Write(data)
-
-	return syscall.Shutdown(int(s.parent.Fd()), syscall.SHUT_WR)
-}
-
-func (s *SyncPipe) ReadFromChild() error {
-	data, err := ioutil.ReadAll(s.parent)
-	if err != nil {
-		return err
-	}
-
-	if len(data) > 0 {
-		return fmt.Errorf("%s", data)
-	}
-
-	return nil
-}
-
-func (s *SyncPipe) ReadFromParent(v interface{}) error {
-	data, err := ioutil.ReadAll(s.child)
-	if err != nil {
-		return fmt.Errorf("error reading from sync pipe %s", err)
-	}
-
-	if len(data) > 0 {
-		if err := json.Unmarshal(data, v); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (s *SyncPipe) ReportChildError(err error) {
-	// ensure that any data sent from the parent is consumed so it doesn't
-	// receive ECONNRESET when the child writes to the pipe.
-	ioutil.ReadAll(s.child)
-
-	s.child.Write([]byte(err.Error()))
-	s.CloseChild()
-}
-
-func (s *SyncPipe) Close() error {
-	if s.parent != nil {
-		s.parent.Close()
-	}
-
-	if s.child != nil {
-		s.child.Close()
-	}
-
-	return nil
-}
-
-func (s *SyncPipe) CloseChild() {
-	if s.child != nil {
-		s.child.Close()
-		s.child = nil
-	}
-}

+ 0 - 20
vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_linux.go

@@ -1,20 +0,0 @@
-package syncpipe
-
-import (
-	"os"
-	"syscall"
-)
-
-func NewSyncPipe() (s *SyncPipe, err error) {
-	s = &SyncPipe{}
-
-	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
-	if err != nil {
-		return nil, err
-	}
-
-	s.child = os.NewFile(uintptr(fds[0]), "child syncpipe")
-	s.parent = os.NewFile(uintptr(fds[1]), "parent syncpipe")
-
-	return s, nil
-}

+ 0 - 72
vendor/src/github.com/docker/libcontainer/syncpipe/sync_pipe_test.go

@@ -1,72 +0,0 @@
-package syncpipe
-
-import (
-	"fmt"
-	"syscall"
-	"testing"
-)
-
-type testStruct struct {
-	Name string
-}
-
-func TestSendErrorFromChild(t *testing.T) {
-	pipe, err := NewSyncPipe()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer func() {
-		if err := pipe.Close(); err != nil {
-			t.Fatal(err)
-		}
-	}()
-
-	childfd, err := syscall.Dup(int(pipe.Child().Fd()))
-	if err != nil {
-		t.Fatal(err)
-	}
-	childPipe, _ := NewSyncPipeFromFd(0, uintptr(childfd))
-
-	pipe.CloseChild()
-	pipe.SendToChild(nil)
-
-	expected := "something bad happened"
-	childPipe.ReportChildError(fmt.Errorf(expected))
-
-	childError := pipe.ReadFromChild()
-	if childError == nil {
-		t.Fatal("expected an error to be returned but did not receive anything")
-	}
-
-	if childError.Error() != expected {
-		t.Fatalf("expected %q but received error message %q", expected, childError.Error())
-	}
-}
-
-func TestSendPayloadToChild(t *testing.T) {
-	pipe, err := NewSyncPipe()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	defer func() {
-		if err := pipe.Close(); err != nil {
-			t.Fatal(err)
-		}
-	}()
-
-	expected := "libcontainer"
-
-	if err := pipe.SendToChild(testStruct{Name: expected}); err != nil {
-		t.Fatal(err)
-	}
-
-	var s *testStruct
-	if err := pipe.ReadFromParent(&s); err != nil {
-		t.Fatal(err)
-	}
-
-	if s.Name != expected {
-		t.Fatalf("expected name %q but received %q", expected, s.Name)
-	}
-}

+ 1 - 0
vendor/src/github.com/docker/libcontainer/system/syscall_linux_amd64.go

@@ -1,4 +1,5 @@
 // +build linux,amd64
+
 package system
 
 import (