Merge pull request #13072 from jfrazelle/bump_v1.6.1

Bump v1.6.1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c54138..a2e22a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
 # Changelog
 
+## 1.6.1 (2015-05-07)
+
+####  Security
+- Fix read/write /proc paths (CVE-2015-3630)
+- Prohibit VOLUME /proc and VOLUME / (CVE-2015-3631)
+- Fix opening of file-descriptor 1 (CVE-2015-3627)
+- Fix symlink traversal on container respawn allowing local privilege escalation (CVE-2015-3629)
+- Prohibit mount of /sys
+
+#### Runtime
+- Update Apparmor policy to not allow mounts
+
 ## 1.6.0 (2015-04-07)
 
 #### Builder
diff --git a/VERSION b/VERSION
index dc1e644..9c6d629 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.0
+1.6.1
diff --git a/daemon/execdriver/native/create.go b/daemon/execdriver/native/create.go
index a988fba..d278249 100644
--- a/daemon/execdriver/native/create.go
+++ b/daemon/execdriver/native/create.go
@@ -6,12 +6,10 @@
 	"errors"
 	"fmt"
 	"net"
-	"path/filepath"
 	"strings"
 	"syscall"
 
 	"github.com/docker/docker/daemon/execdriver"
-	"github.com/docker/docker/pkg/symlink"
 	"github.com/docker/libcontainer/apparmor"
 	"github.com/docker/libcontainer/configs"
 	"github.com/docker/libcontainer/devices"
@@ -228,10 +226,6 @@
 	container.Mounts = defaultMounts
 
 	for _, m := range c.Mounts {
-		dest, err := symlink.FollowSymlinkInScope(filepath.Join(c.Rootfs, m.Destination), c.Rootfs)
-		if err != nil {
-			return err
-		}
 		flags := syscall.MS_BIND | syscall.MS_REC
 		if !m.Writable {
 			flags |= syscall.MS_RDONLY
@@ -239,10 +233,9 @@
 		if m.Slave {
 			flags |= syscall.MS_SLAVE
 		}
-
 		container.Mounts = append(container.Mounts, &configs.Mount{
 			Source:      m.Source,
-			Destination: dest,
+			Destination: m.Destination,
 			Device:      "bind",
 			Flags:       flags,
 		})
diff --git a/daemon/execdriver/native/template/default_template.go b/daemon/execdriver/native/template/default_template.go
index 76e3cea..ecedcfc 100644
--- a/daemon/execdriver/native/template/default_template.go
+++ b/daemon/execdriver/native/template/default_template.go
@@ -82,9 +82,16 @@
 		},
 		MaskPaths: []string{
 			"/proc/kcore",
+			"/proc/latency_stats",
+			"/proc/timer_stats",
 		},
 		ReadonlyPaths: []string{
-			"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
+			"/proc/asound",
+			"/proc/bus",
+			"/proc/fs",
+			"/proc/irq",
+			"/proc/sys",
+			"/proc/sysrq-trigger",
 		},
 	}
 
diff --git a/hack/vendor.sh b/hack/vendor.sh
index bb43771..2a6c409 100755
--- a/hack/vendor.sh
+++ b/hack/vendor.sh
@@ -75,7 +75,7 @@
 mkdir -p src/github.com/docker/distribution
 mv tmp-digest src/github.com/docker/distribution/digest
 
-clone git github.com/docker/libcontainer bd8ec36106086f72b66e1be85a81202b93503e44
+clone git github.com/docker/libcontainer 1b471834b45063b61e0aedefbb1739a8f34b414e
 # 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' | grep -v 'github.com/Sirupsen/logrus')"
diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go
index 9224764..9f7f578 100644
--- a/integration-cli/docker_cli_run_test.go
+++ b/integration-cli/docker_cli_run_test.go
@@ -3436,3 +3436,72 @@
 	}
 	logDone("run - can kill container with pid-host and some childs of pid 1")
 }
+
+func TestRunWithTooSmallMemoryLimit(t *testing.T) {
+	defer deleteAllContainers()
+	// this memory limit is 1 byte less than the min, which is 4MB
+	// https://github.com/docker/docker/blob/v1.5.0/daemon/create.go#L22
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-m", "4194303", "busybox"))
+	if err == nil || !strings.Contains(out, "Minimum memory limit allowed is 4MB") {
+		t.Fatalf("expected run to fail when using too low a memory limit: %q", out)
+	}
+
+	logDone("run - can't set too low memory limit")
+}
+
+func TestRunWriteToProcAsound(t *testing.T) {
+	defer deleteAllContainers()
+	code, err := runCommand(exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "echo 111 >> /proc/asound/version"))
+	if err == nil || code == 0 {
+		t.Fatal("standard container should not be able to write to /proc/asound")
+	}
+	logDone("run - ro write to /proc/asound")
+}
+
+func TestRunReadProcTimer(t *testing.T) {
+	defer deleteAllContainers()
+	out, code, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "busybox", "cat", "/proc/timer_stats"))
+	if err != nil || code != 0 {
+		t.Fatal(err)
+	}
+	if strings.Trim(out, "\n ") != "" {
+		t.Fatalf("expected to receive no output from /proc/timer_stats but received %q", out)
+	}
+	logDone("run - read /proc/timer_stats")
+}
+
+func TestRunReadProcLatency(t *testing.T) {
+	// some kernels don't have this configured so skip the test if this file is not found
+	// on the host running the tests.
+	if _, err := os.Stat("/proc/latency_stats"); err != nil {
+		t.Skip()
+		return
+	}
+	defer deleteAllContainers()
+	out, code, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "busybox", "cat", "/proc/latency_stats"))
+	if err != nil || code != 0 {
+		t.Fatal(err)
+	}
+	if strings.Trim(out, "\n ") != "" {
+		t.Fatalf("expected to receive no output from /proc/latency_stats but received %q", out)
+	}
+	logDone("run - read /proc/latency_stats")
+}
+
+func TestMountIntoProc(t *testing.T) {
+	defer deleteAllContainers()
+	code, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/proc//sys", "busybox", "true"))
+	if err == nil || code == 0 {
+		t.Fatal("container should not be able to mount into /proc")
+	}
+	logDone("run - mount into proc")
+}
+
+func TestMountIntoSys(t *testing.T) {
+	defer deleteAllContainers()
+	code, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/sys/", "busybox", "true"))
+	if err == nil || code == 0 {
+		t.Fatal("container should not be able to mount into /sys")
+	}
+	logDone("run - mount into sys")
+}
diff --git a/vendor/src/github.com/docker/libcontainer/SPEC.md b/vendor/src/github.com/docker/libcontainer/SPEC.md
index d83d758..3ca90d6 100644
--- a/vendor/src/github.com/docker/libcontainer/SPEC.md
+++ b/vendor/src/github.com/docker/libcontainer/SPEC.md
@@ -217,17 +217,6 @@
   file,
   umount,
 
-  mount fstype=tmpfs,
-  mount fstype=mqueue,
-  mount fstype=fuse.*,
-  mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,
-  mount fstype=efivarfs -> /sys/firmware/efi/efivars/,
-  mount fstype=fusectl -> /sys/fs/fuse/connections/,
-  mount fstype=securityfs -> /sys/kernel/security/,
-  mount fstype=debugfs -> /sys/kernel/debug/,
-  mount fstype=proc -> /proc/,
-  mount fstype=sysfs -> /sys/,
-
   deny @{PROC}/sys/fs/** wklx,
   deny @{PROC}/sysrq-trigger rwklx,
   deny @{PROC}/mem rwklx,
@@ -235,9 +224,7 @@
   deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
   deny @{PROC}/sys/kernel/*/** wklx,
 
-  deny mount options=(ro, remount) -> /,
-  deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
-  deny mount fstype=devpts,
+  deny mount,
 
   deny /sys/[^f]*/** wklx,
   deny /sys/f[^s]*/** wklx,
diff --git a/vendor/src/github.com/docker/libcontainer/apparmor/gen.go b/vendor/src/github.com/docker/libcontainer/apparmor/gen.go
index 4565f6d..a3192e2 100644
--- a/vendor/src/github.com/docker/libcontainer/apparmor/gen.go
+++ b/vendor/src/github.com/docker/libcontainer/apparmor/gen.go
@@ -27,17 +27,6 @@
   file,
   umount,
 
-  mount fstype=tmpfs,
-  mount fstype=mqueue,
-  mount fstype=fuse.*,
-  mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/,
-  mount fstype=efivarfs -> /sys/firmware/efi/efivars/,
-  mount fstype=fusectl -> /sys/fs/fuse/connections/,
-  mount fstype=securityfs -> /sys/kernel/security/,
-  mount fstype=debugfs -> /sys/kernel/debug/,
-  mount fstype=proc -> /proc/,
-  mount fstype=sysfs -> /sys/,
-
   deny @{PROC}/sys/fs/** wklx,
   deny @{PROC}/sysrq-trigger rwklx,
   deny @{PROC}/mem rwklx,
@@ -45,9 +34,7 @@
   deny @{PROC}/sys/kernel/[^s][^h][^m]* wklx,
   deny @{PROC}/sys/kernel/*/** wklx,
 
-  deny mount options=(ro, remount) -> /,
-  deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
-  deny mount fstype=devpts,
+  deny mount,
 
   deny /sys/[^f]*/** wklx,
   deny /sys/f[^s]*/** wklx,
diff --git a/vendor/src/github.com/docker/libcontainer/rootfs_linux.go b/vendor/src/github.com/docker/libcontainer/rootfs_linux.go
index ab1a9a5..7a82edb 100644
--- a/vendor/src/github.com/docker/libcontainer/rootfs_linux.go
+++ b/vendor/src/github.com/docker/libcontainer/rootfs_linux.go
@@ -11,6 +11,7 @@
 	"syscall"
 	"time"
 
+	"github.com/docker/docker/pkg/symlink"
 	"github.com/docker/libcontainer/configs"
 	"github.com/docker/libcontainer/label"
 )
@@ -34,11 +35,6 @@
 	if err := setupPtmx(config, console); err != nil {
 		return newSystemError(err)
 	}
-	// stdin, stdout and stderr could be pointing to /dev/null from parent namespace.
-	// re-open them inside this namespace.
-	if err := reOpenDevNull(config.Rootfs); err != nil {
-		return newSystemError(err)
-	}
 	if err := setupDevSymlinks(config.Rootfs); err != nil {
 		return newSystemError(err)
 	}
@@ -53,6 +49,9 @@
 	if err != nil {
 		return newSystemError(err)
 	}
+	if err := reOpenDevNull(config.Rootfs); err != nil {
+		return newSystemError(err)
+	}
 	if config.Readonlyfs {
 		if err := setReadonly(); err != nil {
 			return newSystemError(err)
@@ -105,6 +104,16 @@
 			// unable to bind anything to it.
 			return err
 		}
+		// ensure that the destination of the bind mount is resolved of symlinks at mount time because
+		// any previous mounts can invalidate the next mount's destination.
+		// this can happen when a user specifies mounts within other mounts to cause breakouts or other
+		// evil stuff to try to escape the container's rootfs.
+		if dest, err = symlink.FollowSymlinkInScope(filepath.Join(rootfs, m.Destination), rootfs); err != nil {
+			return err
+		}
+		if err := checkMountDestination(rootfs, dest); err != nil {
+			return err
+		}
 		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
 			return err
 		}
@@ -132,6 +141,29 @@
 	return nil
 }
 
+// checkMountDestination checks to ensure that the mount destination is not over the
+// top of /proc or /sys.
+// dest is required to be an abs path and have any symlinks resolved before calling this function.
+func checkMountDestination(rootfs, dest string) error {
+	if filepath.Clean(rootfs) == filepath.Clean(dest) {
+		return fmt.Errorf("mounting into / is prohibited")
+	}
+	invalidDestinations := []string{
+		"/proc",
+		"/sys",
+	}
+	for _, invalid := range invalidDestinations {
+		path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest)
+		if err != nil {
+			return err
+		}
+		if path == "." || !strings.HasPrefix(path, "..") {
+			return fmt.Errorf("%q cannot be mounted because it is located inside %q", dest, invalid)
+		}
+	}
+	return nil
+}
+
 func setupDevSymlinks(rootfs string) error {
 	var links = [][2]string{
 		{"/proc/self/fd", "/dev/fd"},
@@ -156,11 +188,13 @@
 	return nil
 }
 
-// If stdin, stdout or stderr are pointing to '/dev/null' in the global mount namespace,
-// this method will make them point to '/dev/null' in this namespace.
+// If stdin, stdout, and/or stderr are pointing to `/dev/null` in the parent's rootfs
+// this method will make them point to `/dev/null` in this container's rootfs.  This
+// needs to be called after we chroot/pivot into the container's rootfs so that any
+// symlinks are resolved locally.
 func reOpenDevNull(rootfs string) error {
 	var stat, devNullStat syscall.Stat_t
-	file, err := os.Open(filepath.Join(rootfs, "/dev/null"))
+	file, err := os.Open("/dev/null")
 	if err != nil {
 		return fmt.Errorf("Failed to open /dev/null - %s", err)
 	}
diff --git a/vendor/src/github.com/docker/libcontainer/rootfs_linux_test.go b/vendor/src/github.com/docker/libcontainer/rootfs_linux_test.go
new file mode 100644
index 0000000..54df065
--- /dev/null
+++ b/vendor/src/github.com/docker/libcontainer/rootfs_linux_test.go
@@ -0,0 +1,37 @@
+// +build linux
+
+package libcontainer
+
+import "testing"
+
+func TestCheckMountDestOnProc(t *testing.T) {
+	dest := "/rootfs/proc/"
+	err := checkMountDestination("/rootfs", dest)
+	if err == nil {
+		t.Fatal("destination inside proc should return an error")
+	}
+}
+
+func TestCheckMountDestInSys(t *testing.T) {
+	dest := "/rootfs//sys/fs/cgroup"
+	err := checkMountDestination("/rootfs", dest)
+	if err == nil {
+		t.Fatal("destination inside proc should return an error")
+	}
+}
+
+func TestCheckMountDestFalsePositive(t *testing.T) {
+	dest := "/rootfs/sysfiles/fs/cgroup"
+	err := checkMountDestination("/rootfs", dest)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestCheckMountRoot(t *testing.T) {
+	dest := "/rootfs"
+	err := checkMountDestination("/rootfs", dest)
+	if err == nil {
+		t.Fatal(err)
+	}
+}