Skip to content

Commit

Permalink
Relabel BTRFS Content on container Creation
Browse files Browse the repository at this point in the history
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 <[email protected]>

Signed-off-by: Dan Walsh <[email protected]>
  • Loading branch information
rhatdan committed Nov 11, 2015
1 parent 2a7b5f6 commit 1716d49
Show file tree
Hide file tree
Showing 19 changed files with 72 additions and 62 deletions.
6 changes: 6 additions & 0 deletions daemon/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re
if err := daemon.Register(container); err != nil {
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 {
return nil, err
}
Expand Down
11 changes: 3 additions & 8 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,8 @@ func (daemon *Daemon) createRootfs(container *Container) error {
return err
}
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
}
initPath, err := daemon.driver.Get(initID, "")
Expand All @@ -1012,7 +1013,7 @@ func (daemon *Daemon) createRootfs(container *Container) error {
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 nil
Expand Down Expand Up @@ -1187,12 +1188,6 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, 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
// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
Expand Down
4 changes: 2 additions & 2 deletions daemon/daemon_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ func checkSystem() error {
func configureKernelSecuritySupport(config *Config, driverName string) error {
if config.EnableSelinuxSupport {
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)
}
logrus.Debug("SELinux enabled successfully")
Expand Down
2 changes: 1 addition & 1 deletion daemon/graphdriver/aufs/aufs.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func (a *Driver) Exists(id string) bool {

// Create three folders for each id
// 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 {
return err
}
Expand Down
60 changes: 30 additions & 30 deletions daemon/graphdriver/aufs/aufs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestCreateNewDir(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}
}
Expand All @@ -108,7 +108,7 @@ func TestCreateNewDirStructure(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -129,7 +129,7 @@ func TestRemoveImage(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -154,7 +154,7 @@ func TestGetWithoutParent(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -181,7 +181,7 @@ func TestCleanupWithDir(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -194,7 +194,7 @@ func TestMountedFalseResponse(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -213,10 +213,10 @@ func TestMountedTrueReponse(t *testing.T) {
defer os.RemoveAll(tmp)
defer d.Cleanup()

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}
if err := d.Create("2", "1"); err != nil {
if err := d.Create("2", "1", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -239,10 +239,10 @@ func TestMountWithParent(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}
if err := d.Create("2", "1"); err != nil {
if err := d.Create("2", "1", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -270,10 +270,10 @@ func TestRemoveMountedDir(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}
if err := d.Create("2", "1"); err != nil {
if err := d.Create("2", "1", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -309,7 +309,7 @@ func TestCreateWithInvalidParent(t *testing.T) {
d := newDriver(t)
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")
}
}
Expand All @@ -318,7 +318,7 @@ func TestGetDiff(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -352,10 +352,10 @@ func TestChanges(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}
if err := d.Create("2", "1"); err != nil {
if err := d.Create("2", "1", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -401,7 +401,7 @@ func TestChanges(t *testing.T) {
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)
}
mntPoint, err = d.Get("3", "")
Expand Down Expand Up @@ -446,7 +446,7 @@ func TestDiffSize(t *testing.T) {
d := newDriver(t)
defer os.RemoveAll(tmp)

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -488,7 +488,7 @@ func TestChildDiffSize(t *testing.T) {
defer os.RemoveAll(tmp)
defer d.Cleanup()

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -524,7 +524,7 @@ func TestChildDiffSize(t *testing.T) {
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)
}

Expand All @@ -543,7 +543,7 @@ func TestExists(t *testing.T) {
defer os.RemoveAll(tmp)
defer d.Cleanup()

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -561,7 +561,7 @@ func TestStatus(t *testing.T) {
defer os.RemoveAll(tmp)
defer d.Cleanup()

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -590,7 +590,7 @@ func TestApplyDiff(t *testing.T) {
defer os.RemoveAll(tmp)
defer d.Cleanup()

if err := d.Create("1", ""); err != nil {
if err := d.Create("1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -616,10 +616,10 @@ func TestApplyDiff(t *testing.T) {
t.Fatal(err)
}

if err := d.Create("2", ""); err != nil {
if err := d.Create("2", "", ""); err != nil {
t.Fatal(err)
}
if err := d.Create("3", "2"); err != nil {
if err := d.Create("3", "2", ""); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -647,7 +647,7 @@ func TestHardlinks(t *testing.T) {
origFile := "test_file"
linkedFile := "linked_file"

if err := d.Create("source-1", ""); err != nil {
if err := d.Create("source-1", "", ""); err != nil {
t.Fatal(err)
}

Expand All @@ -667,7 +667,7 @@ func TestHardlinks(t *testing.T) {
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)
}

Expand All @@ -685,15 +685,15 @@ func TestHardlinks(t *testing.T) {
t.Fatal(err)
}

if err := d.Create("target-1", ""); err != nil {
if err := d.Create("target-1", "", ""); err != nil {
t.Fatal(err)
}

if _, err := d.ApplyDiff("target-1", "", layerTar1); err != nil {
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)
}

Expand Down Expand Up @@ -751,7 +751,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
}
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.Error(err)
}
Expand Down
6 changes: 3 additions & 3 deletions daemon/graphdriver/aufs/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string, rootUID,
}

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
}

Expand All @@ -99,7 +99,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string, rootUID,
return err
}

if err := a.Create(id, initID); err != nil {
if err := a.Create(id, initID, ""); err != nil {
return err
}
}
Expand Down Expand Up @@ -153,7 +153,7 @@ func (a *Driver) migrateImage(m *metadata, pth string, migrated map[string]bool)
return err
}
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
}
}
Expand Down
6 changes: 4 additions & 2 deletions daemon/graphdriver/btrfs/btrfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/mount"
"github.com/opencontainers/runc/libcontainer/label"
)

func init() {
Expand Down Expand Up @@ -233,7 +234,7 @@ func (d *Driver) subvolumesDirID(id string) string {
}

// 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")
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil {
Expand All @@ -255,7 +256,8 @@ func (d *Driver) Create(id string, parent string) error {
return err
}
}
return nil

return label.Relabel(path.Join(subvolumes, id), mountLabel, false)
}

// Remove the filesystem with given id.
Expand Down
2 changes: 1 addition & 1 deletion daemon/graphdriver/devmapper/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (d *Driver) Cleanup() error {
}

// 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 {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions daemon/graphdriver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ type ProtoDriver interface {
// String returns a string representation of this driver.
String() string
// 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(id string) error
// Get returns the mountpoint for the layered filesystem referred
Expand Down
Loading

0 comments on commit 1716d49

Please sign in to comment.