瀏覽代碼

Relabel BTRFS Content on container Creation

This change will allow us to run SELinux in a container with
BTRFS back end.  We continue to work on fixing the kernel/BTRFS
but this change will allow SELinux Security separation on BTRFS.

It basically relabels the content on container creation.

Just relabling -init directory in BTRFS use case. Everything looks like it
works. I don't believe tar/achive stores the SELinux labels, so we are good
as far as docker commit.

Tested Speed on startup with BTRFS on top of loopback directory. BTRFS
not on loopback should get even better perfomance on startup time.  The
more inodes inside of the container image will increase the relabel time.

This patch will give people who care more about security the option of
runnin BTRFS with SELinux.  Those who don't want to take the slow down
can disable SELinux either in individual containers or for all containers
by continuing to disable SELinux in the daemon.

Without relabel:

> time docker run --security-opt label:disable fedora echo test
test

real    0m0.918s
user    0m0.009s
sys    0m0.026s

With Relabel

test

real    0m1.942s
user    0m0.007s
sys    0m0.030s

Signed-off-by: Dan Walsh <dwalsh@redhat.com>

Signed-off-by: Dan Walsh <dwalsh@redhat.com>
Dan Walsh 9 年之前
父節點
當前提交
1716d497a4

+ 6 - 0
daemon/create.go

@@ -87,6 +87,12 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re
 	if err := daemon.Register(container); err != nil {
 	if err := daemon.Register(container); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+	container.Lock()
+	if err := parseSecurityOpt(container, params.HostConfig); err != nil {
+		container.Unlock()
+		return nil, err
+	}
+	container.Unlock()
 	if err := daemon.createRootfs(container); err != nil {
 	if err := daemon.createRootfs(container); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 3 - 8
daemon/daemon.go

@@ -991,7 +991,8 @@ func (daemon *Daemon) createRootfs(container *Container) error {
 		return err
 		return err
 	}
 	}
 	initID := fmt.Sprintf("%s-init", container.ID)
 	initID := fmt.Sprintf("%s-init", container.ID)
-	if err := daemon.driver.Create(initID, container.ImageID); err != nil {
+
+	if err := daemon.driver.Create(initID, container.ImageID, container.getMountLabel()); err != nil {
 		return err
 		return err
 	}
 	}
 	initPath, err := daemon.driver.Get(initID, "")
 	initPath, err := daemon.driver.Get(initID, "")
@@ -1012,7 +1013,7 @@ func (daemon *Daemon) createRootfs(container *Container) error {
 		return err
 		return err
 	}
 	}
 
 
-	if err := daemon.driver.Create(container.ID, initID); err != nil {
+	if err := daemon.driver.Create(container.ID, initID, ""); err != nil {
 		return err
 		return err
 	}
 	}
 	return nil
 	return nil
@@ -1187,12 +1188,6 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) {
 }
 }
 
 
 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
-	container.Lock()
-	if err := parseSecurityOpt(container, hostConfig); err != nil {
-		container.Unlock()
-		return err
-	}
-	container.Unlock()
 
 
 	// Do not lock while creating volumes since this could be calling out to external plugins
 	// Do not lock while creating volumes since this could be calling out to external plugins
 	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
 	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin

+ 2 - 2
daemon/daemon_unix.go

@@ -259,8 +259,8 @@ func checkSystem() error {
 func configureKernelSecuritySupport(config *Config, driverName string) error {
 func configureKernelSecuritySupport(config *Config, driverName string) error {
 	if config.EnableSelinuxSupport {
 	if config.EnableSelinuxSupport {
 		if selinuxEnabled() {
 		if selinuxEnabled() {
-			// As Docker on either btrfs or overlayFS and SELinux are incompatible at present, error on both being enabled
-			if driverName == "btrfs" || driverName == "overlay" {
+			// As Docker on overlayFS and SELinux are incompatible at present, error on overlayfs being enabled
+			if driverName == "overlay" {
 				return fmt.Errorf("SELinux is not supported with the %s graph driver", driverName)
 				return fmt.Errorf("SELinux is not supported with the %s graph driver", driverName)
 			}
 			}
 			logrus.Debug("SELinux enabled successfully")
 			logrus.Debug("SELinux enabled successfully")

+ 1 - 1
daemon/graphdriver/aufs/aufs.go

@@ -201,7 +201,7 @@ func (a *Driver) Exists(id string) bool {
 
 
 // Create three folders for each id
 // Create three folders for each id
 // mnt, layers, and diff
 // mnt, layers, and diff
-func (a *Driver) Create(id, parent string) error {
+func (a *Driver) Create(id, parent, mountLabel string) error {
 	if err := a.createDirsFor(id); err != nil {
 	if err := a.createDirsFor(id); err != nil {
 		return err
 		return err
 	}
 	}

+ 30 - 30
daemon/graphdriver/aufs/aufs_test.go

@@ -99,7 +99,7 @@ func TestCreateNewDir(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 }
 }
@@ -108,7 +108,7 @@ func TestCreateNewDirStructure(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -129,7 +129,7 @@ func TestRemoveImage(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -154,7 +154,7 @@ func TestGetWithoutParent(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -181,7 +181,7 @@ func TestCleanupWithDir(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -194,7 +194,7 @@ func TestMountedFalseResponse(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -213,10 +213,10 @@ func TestMountedTrueReponse(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 	defer d.Cleanup()
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := d.Create("2", "1"); err != nil {
+	if err := d.Create("2", "1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -239,10 +239,10 @@ func TestMountWithParent(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := d.Create("2", "1"); err != nil {
+	if err := d.Create("2", "1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -270,10 +270,10 @@ func TestRemoveMountedDir(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := d.Create("2", "1"); err != nil {
+	if err := d.Create("2", "1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -309,7 +309,7 @@ func TestCreateWithInvalidParent(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", "docker"); err == nil {
+	if err := d.Create("1", "docker", ""); err == nil {
 		t.Fatalf("Error should not be nil with parent does not exist")
 		t.Fatalf("Error should not be nil with parent does not exist")
 	}
 	}
 }
 }
@@ -318,7 +318,7 @@ func TestGetDiff(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -352,10 +352,10 @@ func TestChanges(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := d.Create("2", "1"); err != nil {
+	if err := d.Create("2", "1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -401,7 +401,7 @@ func TestChanges(t *testing.T) {
 		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
 		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
 	}
 	}
 
 
-	if err := d.Create("3", "2"); err != nil {
+	if err := d.Create("3", "2", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 	mntPoint, err = d.Get("3", "")
 	mntPoint, err = d.Get("3", "")
@@ -446,7 +446,7 @@ func TestDiffSize(t *testing.T) {
 	d := newDriver(t)
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -488,7 +488,7 @@ func TestChildDiffSize(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 	defer d.Cleanup()
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -524,7 +524,7 @@ func TestChildDiffSize(t *testing.T) {
 		t.Fatalf("Expected size to be %d got %d", size, diffSize)
 		t.Fatalf("Expected size to be %d got %d", size, diffSize)
 	}
 	}
 
 
-	if err := d.Create("2", "1"); err != nil {
+	if err := d.Create("2", "1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -543,7 +543,7 @@ func TestExists(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 	defer d.Cleanup()
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -561,7 +561,7 @@ func TestStatus(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 	defer d.Cleanup()
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -590,7 +590,7 @@ func TestApplyDiff(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 	defer d.Cleanup()
 
 
-	if err := d.Create("1", ""); err != nil {
+	if err := d.Create("1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -616,10 +616,10 @@ func TestApplyDiff(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if err := d.Create("2", ""); err != nil {
+	if err := d.Create("2", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := d.Create("3", "2"); err != nil {
+	if err := d.Create("3", "2", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -647,7 +647,7 @@ func TestHardlinks(t *testing.T) {
 	origFile := "test_file"
 	origFile := "test_file"
 	linkedFile := "linked_file"
 	linkedFile := "linked_file"
 
 
-	if err := d.Create("source-1", ""); err != nil {
+	if err := d.Create("source-1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -667,7 +667,7 @@ func TestHardlinks(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if err := d.Create("source-2", "source-1"); err != nil {
+	if err := d.Create("source-2", "source-1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -685,7 +685,7 @@ func TestHardlinks(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if err := d.Create("target-1", ""); err != nil {
+	if err := d.Create("target-1", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -693,7 +693,7 @@ func TestHardlinks(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if err := d.Create("target-2", "target-1"); err != nil {
+	if err := d.Create("target-2", "target-1", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -751,7 +751,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
 		}
 		}
 		current = hash(current)
 		current = hash(current)
 
 
-		if err := d.Create(current, parent); err != nil {
+		if err := d.Create(current, parent, ""); err != nil {
 			t.Logf("Current layer %d", i)
 			t.Logf("Current layer %d", i)
 			t.Error(err)
 			t.Error(err)
 		}
 		}

+ 3 - 3
daemon/graphdriver/aufs/migrate.go

@@ -86,7 +86,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string, rootUID,
 				}
 				}
 
 
 				initID := fmt.Sprintf("%s-init", id)
 				initID := fmt.Sprintf("%s-init", id)
-				if err := a.Create(initID, metadata.Image); err != nil {
+				if err := a.Create(initID, metadata.Image, ""); err != nil {
 					return err
 					return err
 				}
 				}
 
 
@@ -99,7 +99,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string, rootUID,
 					return err
 					return err
 				}
 				}
 
 
-				if err := a.Create(id, initID); err != nil {
+				if err := a.Create(id, initID, ""); err != nil {
 					return err
 					return err
 				}
 				}
 			}
 			}
@@ -153,7 +153,7 @@ func (a *Driver) migrateImage(m *metadata, pth string, migrated map[string]bool)
 			return err
 			return err
 		}
 		}
 		if !a.Exists(m.ID) {
 		if !a.Exists(m.ID) {
-			if err := a.Create(m.ID, m.ParentID); err != nil {
+			if err := a.Create(m.ID, m.ParentID, ""); err != nil {
 				return err
 				return err
 			}
 			}
 		}
 		}

+ 4 - 2
daemon/graphdriver/btrfs/btrfs.go

@@ -21,6 +21,7 @@ import (
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/mount"
+	"github.com/opencontainers/runc/libcontainer/label"
 )
 )
 
 
 func init() {
 func init() {
@@ -233,7 +234,7 @@ func (d *Driver) subvolumesDirID(id string) string {
 }
 }
 
 
 // Create the filesystem with given id.
 // Create the filesystem with given id.
-func (d *Driver) Create(id string, parent string) error {
+func (d *Driver) Create(id, parent, mountLabel string) error {
 	subvolumes := path.Join(d.home, "subvolumes")
 	subvolumes := path.Join(d.home, "subvolumes")
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	if err != nil {
 	if err != nil {
@@ -255,7 +256,8 @@ func (d *Driver) Create(id string, parent string) error {
 			return err
 			return err
 		}
 		}
 	}
 	}
-	return nil
+
+	return label.Relabel(path.Join(subvolumes, id), mountLabel, false)
 }
 }
 
 
 // Remove the filesystem with given id.
 // Remove the filesystem with given id.

+ 1 - 1
daemon/graphdriver/devmapper/driver.go

@@ -133,7 +133,7 @@ func (d *Driver) Cleanup() error {
 }
 }
 
 
 // Create adds a device with a given id and the parent.
 // Create adds a device with a given id and the parent.
-func (d *Driver) Create(id, parent string) error {
+func (d *Driver) Create(id, parent, mountLabel string) error {
 	if err := d.DeviceSet.AddDevice(id, parent); err != nil {
 	if err := d.DeviceSet.AddDevice(id, parent); err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 2
daemon/graphdriver/driver.go

@@ -48,8 +48,8 @@ type ProtoDriver interface {
 	// String returns a string representation of this driver.
 	// String returns a string representation of this driver.
 	String() string
 	String() string
 	// Create creates a new, empty, filesystem layer with the
 	// Create creates a new, empty, filesystem layer with the
-	// specified id and parent. Parent may be "".
-	Create(id, parent string) error
+	// specified id and parent and mountLabel. Parent and mountLabel may be "".
+	Create(id, parent, mountLabel string) error
 	// Remove attempts to remove the filesystem layer with this id.
 	// Remove attempts to remove the filesystem layer with this id.
 	Remove(id string) error
 	Remove(id string) error
 	// Get returns the mountpoint for the layered filesystem referred
 	// Get returns the mountpoint for the layered filesystem referred

+ 3 - 3
daemon/graphdriver/graphtest/graphtest_unix.go

@@ -177,7 +177,7 @@ func DriverTestCreateEmpty(t *testing.T, drivername string) {
 	driver := GetDriver(t, drivername)
 	driver := GetDriver(t, drivername)
 	defer PutDriver(t)
 	defer PutDriver(t)
 
 
-	if err := driver.Create("empty", ""); err != nil {
+	if err := driver.Create("empty", "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -215,7 +215,7 @@ func createBase(t *testing.T, driver graphdriver.Driver, name string) {
 	oldmask := syscall.Umask(0)
 	oldmask := syscall.Umask(0)
 	defer syscall.Umask(oldmask)
 	defer syscall.Umask(oldmask)
 
 
-	if err := driver.Create(name, ""); err != nil {
+	if err := driver.Create(name, "", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
@@ -283,7 +283,7 @@ func DriverTestCreateSnap(t *testing.T, drivername string) {
 
 
 	createBase(t, driver, "Base")
 	createBase(t, driver, "Base")
 
 
-	if err := driver.Create("Snap", "Base"); err != nil {
+	if err := driver.Create("Snap", "Base", ""); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 

+ 1 - 1
daemon/graphdriver/overlay/overlay.go

@@ -230,7 +230,7 @@ func (d *Driver) Cleanup() error {
 
 
 // Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
 // Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
 // The parent filesystem is used to configure these directories for the overlay.
 // The parent filesystem is used to configure these directories for the overlay.
-func (d *Driver) Create(id string, parent string) (retErr error) {
+func (d *Driver) Create(id, parent, mountLabel string) (retErr error) {
 	dir := d.dir(id)
 	dir := d.dir(id)
 
 
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)

+ 4 - 3
daemon/graphdriver/proxy.go

@@ -55,10 +55,11 @@ func (d *graphDriverProxy) String() string {
 	return d.name
 	return d.name
 }
 }
 
 
-func (d *graphDriverProxy) Create(id, parent string) error {
+func (d *graphDriverProxy) Create(id, parent, mountLabel string) error {
 	args := &graphDriverRequest{
 	args := &graphDriverRequest{
-		ID:     id,
-		Parent: parent,
+		ID:         id,
+		Parent:     parent,
+		MountLabel: mountLabel,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
 	if err := d.client.Call("GraphDriver.Create", args, &ret); err != nil {
 	if err := d.client.Call("GraphDriver.Create", args, &ret); err != nil {

+ 1 - 1
daemon/graphdriver/vfs/driver.go

@@ -66,7 +66,7 @@ func (d *Driver) Cleanup() error {
 }
 }
 
 
 // Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
 // Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
-func (d *Driver) Create(id, parent string) error {
+func (d *Driver) Create(id, parent, mountLabel string) error {
 	dir := d.dir(id)
 	dir := d.dir(id)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 	if err != nil {
 	if err != nil {

+ 1 - 1
daemon/graphdriver/windows/windows.go

@@ -129,7 +129,7 @@ func (d *Driver) Exists(id string) bool {
 }
 }
 
 
 // Create creates a new layer with the given id.
 // Create creates a new layer with the given id.
-func (d *Driver) Create(id, parent string) error {
+func (d *Driver) Create(id, parent, mountLabel string) error {
 	rPId, err := d.resolveID(parent)
 	rPId, err := d.resolveID(parent)
 	if err != nil {
 	if err != nil {
 		return err
 		return err

+ 1 - 1
daemon/graphdriver/zfs/zfs.go

@@ -241,7 +241,7 @@ func (d *Driver) mountPath(id string) string {
 }
 }
 
 
 // Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
 // Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
-func (d *Driver) Create(id string, parent string) error {
+func (d *Driver) Create(id string, parent string, mountLabel string) error {
 	err := d.create(id, parent)
 	err := d.create(id, parent)
 	if err == nil {
 	if err == nil {
 		return nil
 		return nil

+ 6 - 0
daemon/start.go

@@ -29,6 +29,12 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
 		// This is kept for backward compatibility - hostconfig should be passed when
 		// This is kept for backward compatibility - hostconfig should be passed when
 		// creating a container, not during start.
 		// creating a container, not during start.
 		if hostConfig != nil {
 		if hostConfig != nil {
+			container.Lock()
+			if err := parseSecurityOpt(container, hostConfig); err != nil {
+				container.Unlock()
+				return err
+			}
+			container.Unlock()
 			if err := daemon.setHostConfig(container, hostConfig); err != nil {
 			if err := daemon.setHostConfig(container, hostConfig); err != nil {
 				return err
 				return err
 			}
 			}

+ 1 - 1
graph/graph.go

@@ -359,7 +359,7 @@ func (graph *Graph) register(im image.Descriptor, layerData io.Reader) (err erro
 }
 }
 
 
 func createRootFilesystemInDriver(graph *Graph, id, parent string) error {
 func createRootFilesystemInDriver(graph *Graph, id, parent string) error {
-	if err := graph.driver.Create(id, parent); err != nil {
+	if err := graph.driver.Create(id, parent, ""); err != nil {
 		return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, id, err)
 		return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, id, err)
 	}
 	}
 	return nil
 	return nil

+ 1 - 1
integration-cli/docker_cli_external_graphdriver_unix_test.go

@@ -122,7 +122,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
 		if err := decReq(r.Body, &req, w); err != nil {
 		if err := decReq(r.Body, &req, w); err != nil {
 			return
 			return
 		}
 		}
-		if err := driver.Create(req.ID, req.Parent); err != nil {
+		if err := driver.Create(req.ID, req.Parent, ""); err != nil {
 			respond(w, err)
 			respond(w, err)
 			return
 			return
 		}
 		}

+ 1 - 1
man/docker-daemon.8.md

@@ -191,7 +191,7 @@ unix://[/path/to/socket] to use.
   Force the Docker runtime to use a specific storage driver.
   Force the Docker runtime to use a specific storage driver.
 
 
 **--selinux-enabled**=*true*|*false*
 **--selinux-enabled**=*true*|*false*
-  Enable selinux support. Default is false. SELinux does not presently support the BTRFS storage driver.
+  Enable selinux support. Default is false. SELinux does not presently support the overlay storage driver.
 
 
 **--storage-opt**=[]
 **--storage-opt**=[]
   Set storage driver options. See STORAGE DRIVER OPTIONS.
   Set storage driver options. See STORAGE DRIVER OPTIONS.