From f0e6e135a8d733af173bf0b8732c704c9ec716d7 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 17 Apr 2014 23:47:27 +0000 Subject: [PATCH 1/8] Initial work on selinux patch This has every container using the docker daemon's pid for the processes label so it does not work correctly. Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- daemon/container.go | 20 ++++-- daemon/daemon.go | 15 ++-- daemon/execdriver/native/create.go | 12 +--- daemon/graphdriver/aufs/aufs.go | 31 ++++---- daemon/graphdriver/aufs/aufs_test.go | 78 ++++++++++----------- daemon/graphdriver/aufs/migrate.go | 8 +-- daemon/graphdriver/btrfs/btrfs.go | 10 +-- daemon/graphdriver/devmapper/deviceset.go | 8 ++- daemon/graphdriver/devmapper/driver.go | 4 +- daemon/graphdriver/devmapper/driver_test.go | 45 ++++++------ daemon/graphdriver/driver.go | 4 +- daemon/graphdriver/vfs/driver.go | 6 +- daemon/volumes.go | 2 +- daemonconfig/config.go | 3 +- docker/docker.go | 2 + graph/graph.go | 8 +-- image/image.go | 6 +- integration/graph_test.go | 2 +- integration/runtime_test.go | 4 +- pkg/label/label_selinux.go | 8 +-- pkg/libcontainer/nsinit/init.go | 3 +- 21 files changed, 148 insertions(+), 131 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index c06fd2c074..4416a4c212 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -11,6 +11,7 @@ import ( "github.com/dotcloud/docker/image" "github.com/dotcloud/docker/links" "github.com/dotcloud/docker/nat" + "github.com/dotcloud/docker/pkg/selinux" "github.com/dotcloud/docker/runconfig" "github.com/dotcloud/docker/utils" "io" @@ -64,7 +65,8 @@ type Container struct { stdin io.ReadCloser stdinPipe io.WriteCloser - daemon *Daemon + daemon *Daemon + mountLabel, processLabel string waitLock chan struct{} Volumes map[string]string @@ -320,9 +322,11 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s func populateCommand(c *Container, env []string) { var ( - en *execdriver.Network - driverConfig = make(map[string][]string) + en *execdriver.Network + context = make(map[string][]string) ) + context["process_label"] = []string{c.processLabel} + context["mount_label"] = []string{c.mountLabel} en = &execdriver.Network{ Mtu: c.daemon.config.Mtu, @@ -340,7 +344,7 @@ func populateCommand(c *Container, env []string) { } // TODO: this can be removed after lxc-conf is fully deprecated - mergeLxcConfIntoOptions(c.hostConfig, driverConfig) + mergeLxcConfIntoOptions(c.hostConfig, context) resources := &execdriver.Resources{ Memory: c.Config.Memory, @@ -358,7 +362,7 @@ func populateCommand(c *Container, env []string) { Network: en, Tty: c.Config.Tty, User: c.Config.User, - Config: driverConfig, + Config: context, Resources: resources, } c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true} @@ -383,6 +387,12 @@ func (container *Container) Start() (err error) { if err := container.setupContainerDns(); err != nil { return err } + + process, mount := selinux.GetLxcContexts() + + container.mountLabel = mount + container.processLabel = process + if err := container.Mount(); err != nil { return err } diff --git a/daemon/daemon.go b/daemon/daemon.go index 0e4d1a1699..50707fbc98 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -543,10 +543,10 @@ func (daemon *Daemon) createRootfs(container *Container, img *image.Image) error return err } initID := fmt.Sprintf("%s-init", container.ID) - if err := daemon.driver.Create(initID, img.ID, ""); err != nil { + if err := daemon.driver.Create(initID, img.ID); err != nil { return err } - initPath, err := daemon.driver.Get(initID) + initPath, err := daemon.driver.Get(initID, "") if err != nil { return err } @@ -556,7 +556,7 @@ func (daemon *Daemon) createRootfs(container *Container, img *image.Image) 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 @@ -670,7 +670,6 @@ func NewDaemonFromDirectory(config *daemonconfig.Config, eng *engine.Engine) (*D if !config.EnableSelinuxSupport { selinux.SetDisabled() } - // Set the default driver graphdriver.DefaultDriver = config.GraphDriver @@ -840,7 +839,7 @@ func (daemon *Daemon) Close() error { } func (daemon *Daemon) Mount(container *Container) error { - dir, err := daemon.driver.Get(container.ID) + dir, err := daemon.driver.Get(container.ID, container.mountLabel) if err != nil { return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) } @@ -862,12 +861,12 @@ func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) { if differ, ok := daemon.driver.(graphdriver.Differ); ok { return differ.Changes(container.ID) } - cDir, err := daemon.driver.Get(container.ID) + cDir, err := daemon.driver.Get(container.ID, "") if err != nil { return nil, fmt.Errorf("Error getting container rootfs %s from driver %s: %s", container.ID, container.daemon.driver, err) } defer daemon.driver.Put(container.ID) - initDir, err := daemon.driver.Get(container.ID + "-init") + initDir, err := daemon.driver.Get(container.ID+"-init", "") if err != nil { return nil, fmt.Errorf("Error getting container init rootfs %s from driver %s: %s", container.ID, container.daemon.driver, err) } @@ -885,7 +884,7 @@ func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) { return nil, err } - cDir, err := daemon.driver.Get(container.ID) + cDir, err := daemon.driver.Get(container.ID, "") if err != nil { return nil, fmt.Errorf("Error getting container rootfs %s from driver %s: %s", container.ID, container.daemon.driver, err) } diff --git a/daemon/execdriver/native/create.go b/daemon/execdriver/native/create.go index f724ef67e6..00e6fc4b26 100644 --- a/daemon/execdriver/native/create.go +++ b/daemon/execdriver/native/create.go @@ -8,7 +8,6 @@ import ( "github.com/dotcloud/docker/daemon/execdriver/native/configuration" "github.com/dotcloud/docker/daemon/execdriver/native/template" "github.com/dotcloud/docker/pkg/apparmor" - "github.com/dotcloud/docker/pkg/label" "github.com/dotcloud/docker/pkg/libcontainer" ) @@ -119,14 +118,7 @@ func (d *driver) setupMounts(container *libcontainer.Container, c *execdriver.Co } func (d *driver) setupLabels(container *libcontainer.Container, c *execdriver.Command) error { - labels := c.Config["label"] - if len(labels) > 0 { - process, mount, err := label.GenLabels(labels[0]) - if err != nil { - return err - } - container.Context["mount_label"] = mount - container.Context["process_label"] = process - } + container.Context["process_label"] = c.Config["process_label"][0] + container.Context["mount_label"] = c.Config["mount_label"][0] return nil } diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index 8363c24a5e..12b7a77fb3 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -25,6 +25,7 @@ import ( "fmt" "github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/daemon/graphdriver" + "github.com/dotcloud/docker/pkg/label" mountpk "github.com/dotcloud/docker/pkg/mount" "github.com/dotcloud/docker/utils" "os" @@ -134,7 +135,7 @@ func (a Driver) Exists(id string) bool { // Three folders are created for each id // mnt, layers, and diff -func (a *Driver) Create(id, parent string, mountLabel string) error { +func (a *Driver) Create(id, parent string) error { if err := a.createDirsFor(id); err != nil { return err } @@ -218,7 +219,7 @@ func (a *Driver) Remove(id string) error { // Return the rootfs path for the id // This will mount the dir at it's given path -func (a *Driver) Get(id string) (string, error) { +func (a *Driver) Get(id, mountLabel string) (string, error) { ids, err := getParentIds(a.rootPath(), id) if err != nil { if !os.IsNotExist(err) { @@ -240,7 +241,7 @@ func (a *Driver) Get(id string) (string, error) { out = path.Join(a.rootPath(), "mnt", id) if count == 0 { - if err := a.mount(id); err != nil { + if err := a.mount(id, mountLabel); err != nil { return "", err } } @@ -309,7 +310,7 @@ func (a *Driver) getParentLayerPaths(id string) ([]string, error) { return layers, nil } -func (a *Driver) mount(id string) error { +func (a *Driver) mount(id, mountLabel string) error { // If the id is mounted or we get an error return if mounted, err := a.mounted(id); err != nil || mounted { return err @@ -325,7 +326,7 @@ func (a *Driver) mount(id string) error { return err } - if err := a.aufsMount(layers, rw, target); err != nil { + if err := a.aufsMount(layers, rw, target, mountLabel); err != nil { return err } return nil @@ -358,21 +359,21 @@ func (a *Driver) Cleanup() error { return nil } -func (a *Driver) aufsMount(ro []string, rw, target string) (err error) { +func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) { defer func() { if err != nil { Unmount(target) } }() - if err = a.tryMount(ro, rw, target); err != nil { - if err = a.mountRw(rw, target); err != nil { + if err = a.tryMount(ro, rw, target, mountLabel); err != nil { + if err = a.mountRw(rw, target, mountLabel); err != nil { return } for _, layer := range ro { - branch := fmt.Sprintf("append:%s=ro+wh", layer) - if err = mount("none", target, "aufs", MsRemount, branch); err != nil { + data := label.FormatMountLabel(fmt.Sprintf("append:%s=ro+wh", layer), mountLabel) + if err = mount("none", target, "aufs", MsRemount, data); err != nil { return } } @@ -382,16 +383,18 @@ func (a *Driver) aufsMount(ro []string, rw, target string) (err error) { // Try to mount using the aufs fast path, if this fails then // append ro layers. -func (a *Driver) tryMount(ro []string, rw, target string) (err error) { +func (a *Driver) tryMount(ro []string, rw, target, mountLabel string) (err error) { var ( rwBranch = fmt.Sprintf("%s=rw", rw) roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:")) + data = label.FormatMountLabel(fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches), mountLabel) ) - return mount("none", target, "aufs", 0, fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches)) + return mount("none", target, "aufs", 0, data) } -func (a *Driver) mountRw(rw, target string) error { - return mount("none", target, "aufs", 0, fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw)) +func (a *Driver) mountRw(rw, target, mountLabel string) error { + data := label.FormatMountLabel(fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw), mountLabel) + return mount("none", target, "aufs", 0, data) } func rollbackMount(target string, err error) { diff --git a/daemon/graphdriver/aufs/aufs_test.go b/daemon/graphdriver/aufs/aufs_test.go index 9e01a945aa..1ffa264aa1 100644 --- a/daemon/graphdriver/aufs/aufs_test.go +++ b/daemon/graphdriver/aufs/aufs_test.go @@ -90,7 +90,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) } } @@ -99,7 +99,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) } @@ -120,7 +120,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) } @@ -145,11 +145,11 @@ 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) } - diffPath, err := d.Get("1") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -172,7 +172,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) } @@ -185,7 +185,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) } @@ -204,14 +204,14 @@ 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) } - _, err := d.Get("2") + _, err := d.Get("2", "") if err != nil { t.Fatal(err) } @@ -230,10 +230,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) } @@ -243,7 +243,7 @@ func TestMountWithParent(t *testing.T) { } }() - mntPath, err := d.Get("2") + mntPath, err := d.Get("2", "") if err != nil { t.Fatal(err) } @@ -261,10 +261,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) } @@ -274,7 +274,7 @@ func TestRemoveMountedDir(t *testing.T) { } }() - mntPath, err := d.Get("2") + mntPath, err := d.Get("2", "") if err != nil { t.Fatal(err) } @@ -300,7 +300,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") } } @@ -309,11 +309,11 @@ 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) } - diffPath, err := d.Get("1") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -343,10 +343,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) } @@ -356,7 +356,7 @@ func TestChanges(t *testing.T) { } }() - mntPoint, err := d.Get("2") + mntPoint, err := d.Get("2", "") if err != nil { t.Fatal(err) } @@ -392,10 +392,10 @@ 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") + mntPoint, err = d.Get("3", "") if err != nil { t.Fatal(err) } @@ -437,11 +437,11 @@ 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) } - diffPath, err := d.Get("1") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -479,11 +479,11 @@ 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) } - diffPath, err := d.Get("1") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -515,7 +515,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) } @@ -534,7 +534,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) } @@ -552,7 +552,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) } @@ -581,11 +581,11 @@ 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) } - diffPath, err := d.Get("1") + diffPath, err := d.Get("1", "") if err != nil { t.Fatal(err) } @@ -607,10 +607,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) } @@ -620,7 +620,7 @@ func TestApplyDiff(t *testing.T) { // Ensure that the file is in the mount point for id 3 - mountPoint, err := d.Get("3") + mountPoint, err := d.Get("3", "") if err != nil { t.Fatal(err) } @@ -656,11 +656,11 @@ func TestMountMoreThan42Layers(t *testing.T) { } 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.Fatal(err) } - point, err := d.Get(current) + point, err := d.Get(current, "") if err != nil { t.Logf("Current layer %d", i) t.Fatal(err) @@ -683,7 +683,7 @@ func TestMountMoreThan42Layers(t *testing.T) { } // Perform the actual mount for the top most image - point, err := d.Get(last) + point, err := d.Get(last, "") if err != nil { t.Fatal(err) } diff --git a/daemon/graphdriver/aufs/migrate.go b/daemon/graphdriver/aufs/migrate.go index 400e260797..dda7cb7390 100644 --- a/daemon/graphdriver/aufs/migrate.go +++ b/daemon/graphdriver/aufs/migrate.go @@ -77,11 +77,11 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string) error) e } 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 } - initPath, err := a.Get(initID) + initPath, err := a.Get(initID, "") if err != nil { return err } @@ -90,7 +90,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string) error) e return err } - if err := a.Create(id, initID, ""); err != nil { + if err := a.Create(id, initID); err != nil { return err } } @@ -144,7 +144,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 } } diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go index 494a375817..4d195537eb 100644 --- a/daemon/graphdriver/btrfs/btrfs.go +++ b/daemon/graphdriver/btrfs/btrfs.go @@ -80,7 +80,7 @@ func getDirFd(dir *C.DIR) uintptr { return uintptr(C.dirfd(dir)) } -func subvolCreate(path, name string, mountLabel string) error { +func subvolCreate(path, name string) error { dir, err := openDir(path) if err != nil { return err @@ -155,17 +155,17 @@ func (d *Driver) subvolumesDirId(id string) string { return path.Join(d.subvolumesDir(), id) } -func (d *Driver) Create(id string, parent string, mountLabel string) error { +func (d *Driver) Create(id string, parent string) error { subvolumes := path.Join(d.home, "subvolumes") if err := os.MkdirAll(subvolumes, 0700); err != nil { return err } if parent == "" { - if err := subvolCreate(subvolumes, id, mountLabel); err != nil { + if err := subvolCreate(subvolumes, id); err != nil { return err } } else { - parentDir, err := d.Get(parent) + parentDir, err := d.Get(parent, "") if err != nil { return err } @@ -187,7 +187,7 @@ func (d *Driver) Remove(id string) error { return os.RemoveAll(dir) } -func (d *Driver) Get(id string) (string, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { dir := d.subvolumesDirId(id) st, err := os.Stat(dir) if err != nil { diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index 640bebd32b..a562210e55 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -845,7 +845,7 @@ func (devices *DeviceSet) Shutdown() error { return nil } -func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) error { +func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { info, err := devices.lookupDevice(hash) if err != nil { return err @@ -858,6 +858,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro defer devices.Unlock() if info.mountCount > 0 { + fmt.Printf("---> already mounted\n") if path != info.mountPath { return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path) } @@ -873,9 +874,12 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro var flags uintptr = sysMsMgcVal mountOptions := label.FormatMountLabel("discard", mountLabel) + fmt.Printf("-----> setting mount label %s\n", mountOptions) + err = sysMount(info.DevName(), path, "ext4", flags, mountOptions) if err != nil && err == sysEInval { - mountOptions = label.FormatMountLabel(mountLabel, "") + mountOptions = label.FormatMountLabel("", mountLabel) + fmt.Printf("-----> setting mount label after error %s\n", mountOptions) err = sysMount(info.DevName(), path, "ext4", flags, mountOptions) } if err != nil { diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 66c4cb0767..558feef327 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -60,7 +60,7 @@ func (d *Driver) Cleanup() error { return d.DeviceSet.Shutdown() } -func (d *Driver) Create(id, parent string, mountLabel string) error { +func (d *Driver) Create(id, parent string) error { if err := d.DeviceSet.AddDevice(id, parent); err != nil { return err } @@ -89,7 +89,7 @@ func (d *Driver) Remove(id string) error { return nil } -func (d *Driver) Get(id string) (string, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { mp := path.Join(d.home, "mnt", id) // Create the target directories if they don't exist diff --git a/daemon/graphdriver/devmapper/driver_test.go b/daemon/graphdriver/devmapper/driver_test.go index 77e8a6013a..913add7c8b 100644 --- a/daemon/graphdriver/devmapper/driver_test.go +++ b/daemon/graphdriver/devmapper/driver_test.go @@ -436,6 +436,12 @@ func TestDriverCreate(t *testing.T) { return nil } + sysUnmount = func(target string, flag int) error { + //calls["sysUnmount"] = true + + return nil + } + Mounted = func(mnt string) (bool, error) { calls["Mounted"] = true if !strings.HasPrefix(mnt, "/tmp/docker-test-devmapper-") || !strings.HasSuffix(mnt, "/mnt/1") { @@ -494,7 +500,7 @@ func TestDriverCreate(t *testing.T) { "?ioctl.loopctlgetfree", ) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } calls.Assert(t, @@ -542,7 +548,6 @@ func TestDriverRemove(t *testing.T) { return nil } sysUnmount = func(target string, flags int) (err error) { - calls["sysUnmount"] = true // FIXME: compare the exact source and target strings (inodes + devname) if expectedTarget := "/tmp/docker-test-devmapper-"; !strings.HasPrefix(target, expectedTarget) { t.Fatalf("Wrong syscall call\nExpected: Mount(%v)\nReceived: Mount(%v)\n", expectedTarget, target) @@ -607,7 +612,7 @@ func TestDriverRemove(t *testing.T) { "?ioctl.loopctlgetfree", ) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } @@ -657,21 +662,21 @@ func TestCleanup(t *testing.T) { mountPoints := make([]string, 2) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } // Mount the id - p, err := d.Get("1") + p, err := d.Get("1", "") if err != nil { t.Fatal(err) } mountPoints[0] = p - if err := d.Create("2", "1", ""); err != nil { + if err := d.Create("2", "1"); err != nil { t.Fatal(err) } - p, err = d.Get("2") + p, err = d.Get("2", "") if err != nil { t.Fatal(err) } @@ -720,7 +725,7 @@ func TestNotMounted(t *testing.T) { d := newDriver(t) defer cleanup(d) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } @@ -738,10 +743,10 @@ func TestMounted(t *testing.T) { d := newDriver(t) defer cleanup(d) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } @@ -758,10 +763,10 @@ func TestInitCleanedDriver(t *testing.T) { t.Skip("FIXME: not a unit test") d := newDriver(t) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } @@ -776,7 +781,7 @@ func TestInitCleanedDriver(t *testing.T) { d = driver.(*Driver) defer cleanup(d) - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } } @@ -786,16 +791,16 @@ func TestMountMountedDriver(t *testing.T) { d := newDriver(t) defer cleanup(d) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } // Perform get on same id to ensure that it will // not be mounted twice - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } } @@ -805,7 +810,7 @@ func TestGetReturnsValidDevice(t *testing.T) { d := newDriver(t) defer cleanup(d) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } @@ -813,7 +818,7 @@ func TestGetReturnsValidDevice(t *testing.T) { t.Fatalf("Expected id 1 to be in device set") } - if _, err := d.Get("1"); err != nil { + if _, err := d.Get("1", ""); err != nil { t.Fatal(err) } @@ -833,11 +838,11 @@ func TestDriverGetSize(t *testing.T) { d := newDriver(t) defer cleanup(d) - if err := d.Create("1", "", ""); err != nil { + if err := d.Create("1", ""); err != nil { t.Fatal(err) } - mountPoint, err := d.Get("1") + mountPoint, err := d.Get("1", "") if err != nil { t.Fatal(err) } diff --git a/daemon/graphdriver/driver.go b/daemon/graphdriver/driver.go index bd4c2faaca..80bf8a0143 100644 --- a/daemon/graphdriver/driver.go +++ b/daemon/graphdriver/driver.go @@ -13,10 +13,10 @@ type InitFunc func(root string) (Driver, error) type Driver interface { String() string - Create(id, parent string, mountLabel string) error + Create(id, parent string) error Remove(id string) error - Get(id string) (dir string, err error) + Get(id, mountLabel string) (dir string, err error) Put(id string) Exists(id string) bool diff --git a/daemon/graphdriver/vfs/driver.go b/daemon/graphdriver/vfs/driver.go index 40acde7b75..765b21cded 100644 --- a/daemon/graphdriver/vfs/driver.go +++ b/daemon/graphdriver/vfs/driver.go @@ -42,7 +42,7 @@ func copyDir(src, dst string) error { return nil } -func (d *Driver) Create(id string, parent string, mountLabel string) error { +func (d *Driver) Create(id, parent string) error { dir := d.dir(id) if err := os.MkdirAll(path.Dir(dir), 0700); err != nil { return err @@ -53,7 +53,7 @@ func (d *Driver) Create(id string, parent string, mountLabel string) error { if parent == "" { return nil } - parentDir, err := d.Get(parent) + parentDir, err := d.Get(parent, "") if err != nil { return fmt.Errorf("%s: %s", parent, err) } @@ -74,7 +74,7 @@ func (d *Driver) Remove(id string) error { return os.RemoveAll(d.dir(id)) } -func (d *Driver) Get(id string) (string, error) { +func (d *Driver) Get(id, mountLabel string) (string, error) { dir := d.dir(id) if st, err := os.Stat(dir); err != nil { return "", err diff --git a/daemon/volumes.go b/daemon/volumes.go index d51219d226..a6570845bf 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -204,7 +204,7 @@ func createVolumes(container *Container) error { if err != nil { return err } - srcPath, err = volumesDriver.Get(c.ID) + srcPath, err = volumesDriver.Get(c.ID, "") if err != nil { return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err) } diff --git a/daemonconfig/config.go b/daemonconfig/config.go index 2803f827f4..87ac52224d 100644 --- a/daemonconfig/config.go +++ b/daemonconfig/config.go @@ -29,6 +29,7 @@ type Config struct { Mtu int DisableNetwork bool EnableSelinuxSupport bool + Context map[string][]string } // ConfigFromJob creates and returns a new DaemonConfig object @@ -46,7 +47,7 @@ func ConfigFromJob(job *engine.Job) *Config { InterContainerCommunication: job.GetenvBool("InterContainerCommunication"), GraphDriver: job.Getenv("GraphDriver"), ExecDriver: job.Getenv("ExecDriver"), - EnableSelinuxSupport: false, // FIXME: hardcoded default to disable selinux for .10 release + EnableSelinuxSupport: job.GetenvBool("SelinuxEnabled"), } if dns := job.GetenvList("Dns"); dns != nil { config.Dns = dns diff --git a/docker/docker.go b/docker/docker.go index 4d90ab8b2e..ce3c54dacd 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -64,6 +64,7 @@ func main() { flCa = flag.String([]string{"-tlscacert"}, dockerConfDir+defaultCaFile, "Trust only remotes providing a certificate signed by the CA given here") flCert = flag.String([]string{"-tlscert"}, dockerConfDir+defaultCertFile, "Path to TLS certificate file") flKey = flag.String([]string{"-tlskey"}, dockerConfDir+defaultKeyFile, "Path to TLS key file") + flSelinuxEnabled = flag.Bool([]string{"-selinux-enabled"}, false, "Enable selinux support") ) flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers") flag.Var(&flDnsSearch, []string{"-dns-search"}, "Force Docker to use specific DNS search domains") @@ -148,6 +149,7 @@ func main() { job.Setenv("GraphDriver", *flGraphDriver) job.Setenv("ExecDriver", *flExecDriver) job.SetenvInt("Mtu", *flMtu) + job.SetenvBool("SelinuxEnabled", *flSelinuxEnabled) if err := job.Run(); err != nil { log.Fatal(err) } diff --git a/graph/graph.go b/graph/graph.go index 5c3a94bab7..b889139121 100644 --- a/graph/graph.go +++ b/graph/graph.go @@ -98,7 +98,7 @@ func (graph *Graph) Get(name string) (*image.Image, error) { img.SetGraph(graph) if img.Size < 0 { - rootfs, err := graph.driver.Get(img.ID) + rootfs, err := graph.driver.Get(img.ID, "") if err != nil { return nil, fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err) } @@ -110,7 +110,7 @@ func (graph *Graph) Get(name string) (*image.Image, error) { return nil, err } } else { - parentFs, err := graph.driver.Get(img.Parent) + parentFs, err := graph.driver.Get(img.Parent, "") if err != nil { return nil, err } @@ -191,11 +191,11 @@ func (graph *Graph) Register(jsonData []byte, layerData archive.ArchiveReader, i } // Create root filesystem in the driver - if err := graph.driver.Create(img.ID, img.Parent, ""); err != nil { + if err := graph.driver.Create(img.ID, img.Parent); err != nil { return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err) } // Mount the root filesystem so we can apply the diff/layer - rootfs, err := graph.driver.Get(img.ID) + rootfs, err := graph.driver.Get(img.ID, "") if err != nil { return fmt.Errorf("Driver %s failed to get image rootfs %s: %s", graph.driver, img.ID, err) } diff --git a/image/image.go b/image/image.go index 239e5cc055..b56cbf08ee 100644 --- a/image/image.go +++ b/image/image.go @@ -98,7 +98,7 @@ func StoreImage(img *Image, jsonData []byte, layerData archive.ArchiveReader, ro return err } } else { - parent, err := driver.Get(img.Parent) + parent, err := driver.Get(img.Parent, "") if err != nil { return err } @@ -159,7 +159,7 @@ func (img *Image) TarLayer() (arch archive.Archive, err error) { return differ.Diff(img.ID) } - imgFs, err := driver.Get(img.ID) + imgFs, err := driver.Get(img.ID, "") if err != nil { return nil, err } @@ -182,7 +182,7 @@ func (img *Image) TarLayer() (arch archive.Archive, err error) { }), nil } - parentFs, err := driver.Get(img.Parent) + parentFs, err := driver.Get(img.Parent, "") if err != nil { return nil, err } diff --git a/integration/graph_test.go b/integration/graph_test.go index a7a8137284..c29055edfc 100644 --- a/integration/graph_test.go +++ b/integration/graph_test.go @@ -43,7 +43,7 @@ func TestMount(t *testing.T) { t.Fatal(err) } - if _, err := driver.Get(image.ID); err != nil { + if _, err := driver.Get(image.ID, ""); err != nil { t.Fatal(err) } } diff --git a/integration/runtime_test.go b/integration/runtime_test.go index bf00437547..c84ea5bed2 100644 --- a/integration/runtime_test.go +++ b/integration/runtime_test.go @@ -874,12 +874,12 @@ func TestDestroyWithInitLayer(t *testing.T) { driver := daemon.Graph().Driver() // Make sure that the container does not exist in the driver - if _, err := driver.Get(container.ID); err == nil { + if _, err := driver.Get(container.ID, ""); err == nil { t.Fatal("Conttainer should not exist in the driver") } // Make sure that the init layer is removed from the driver - if _, err := driver.Get(fmt.Sprintf("%s-init", container.ID)); err == nil { + if _, err := driver.Get(fmt.Sprintf("%s-init", container.ID), ""); err == nil { t.Fatal("Container's init layer should not exist in the driver") } } diff --git a/pkg/label/label_selinux.go b/pkg/label/label_selinux.go index 9f7463f79b..2f67ee458f 100644 --- a/pkg/label/label_selinux.go +++ b/pkg/label/label_selinux.go @@ -32,13 +32,13 @@ func GenLabels(options string) (string, string, error) { return processLabel, mountLabel, err } -func FormatMountLabel(src string, mountLabel string) string { - if selinux.SelinuxEnabled() && mountLabel != "" { +func FormatMountLabel(src, mountLabel string) string { + if mountLabel != "" { switch src { case "": - src = fmt.Sprintf("%s,context=%s", src, mountLabel) + src = fmt.Sprintf("context=%q", mountLabel) default: - src = fmt.Sprintf("context=%s", mountLabel) + src = fmt.Sprintf("%s,context=%q", src, mountLabel) } } return src diff --git a/pkg/libcontainer/nsinit/init.go b/pkg/libcontainer/nsinit/init.go index 4e50bc513b..36c8cd1245 100644 --- a/pkg/libcontainer/nsinit/init.go +++ b/pkg/libcontainer/nsinit/init.go @@ -75,8 +75,9 @@ func (ns *linuxNs) Init(container *libcontainer.Container, uncleanRootfs, consol } } runtime.LockOSThread() + if err := label.SetProcessLabel(container.Context["process_label"]); err != nil { - return fmt.Errorf("SetProcessLabel label %s", err) + return fmt.Errorf("set process label %s", err) } ns.logger.Printf("execing %s\n", args[0]) return system.Execv(args[0], args[0:], container.Env) From b7942ec2ca7c7568df0c3b7eb554b05e2c3a3081 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 21 Apr 2014 17:09:26 -0400 Subject: [PATCH 2/8] This patch reworks the SELinux patch to be only run on demand by the daemon Added --selinux-enable switch to daemon to enable SELinux labeling. The daemon will now generate a new unique random SELinux label when a container starts, and remove it when the container is removed. The MCS labels will be stored in the daemon memory. The labels of containers will be stored in the container.json file. When the daemon restarts on boot or if done by an admin, it will read all containers json files and reserve the MCS labels. A potential problem would be conflicts if you setup thousands of containers, current scheme would handle ~500,000 containers. Docker-DCO-1.1-Signed-off-by: Dan Walsh (github: rhatdan) Docker-DCO-1.1-Signed-off-by: Dan Walsh (github: crosbymichael) --- daemon/container.go | 18 +++++++++++------- daemon/daemon.go | 4 +++- daemonconfig/config.go | 2 +- docker/docker.go | 2 +- pkg/label/label.go | 4 ++++ pkg/label/label_selinux.go | 4 ++++ pkg/selinux/selinux.go | 28 ++++++++++++++++++++++++---- pkg/selinux/selinux_test.go | 2 ++ 8 files changed, 50 insertions(+), 14 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index 4416a4c212..2190869da0 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -11,7 +11,7 @@ import ( "github.com/dotcloud/docker/image" "github.com/dotcloud/docker/links" "github.com/dotcloud/docker/nat" - "github.com/dotcloud/docker/pkg/selinux" + "github.com/dotcloud/docker/pkg/label" "github.com/dotcloud/docker/runconfig" "github.com/dotcloud/docker/utils" "io" @@ -66,7 +66,7 @@ type Container struct { stdinPipe io.WriteCloser daemon *Daemon - mountLabel, processLabel string + MountLabel, ProcessLabel string waitLock chan struct{} Volumes map[string]string @@ -124,6 +124,7 @@ func (container *Container) FromDisk() error { if err := json.Unmarshal(data, container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") { return err } + label.ReserveLabel(container.ProcessLabel) return container.readHostConfig() } @@ -325,8 +326,8 @@ func populateCommand(c *Container, env []string) { en *execdriver.Network context = make(map[string][]string) ) - context["process_label"] = []string{c.processLabel} - context["mount_label"] = []string{c.mountLabel} + context["process_label"] = []string{c.ProcessLabel} + context["mount_label"] = []string{c.MountLabel} en = &execdriver.Network{ Mtu: c.daemon.config.Mtu, @@ -388,10 +389,13 @@ func (container *Container) Start() (err error) { return err } - process, mount := selinux.GetLxcContexts() + process, mount, err := label.GenLabels("") + if err != nil { + return err + } - container.mountLabel = mount - container.processLabel = process + container.MountLabel = mount + container.ProcessLabel = process if err := container.Mount(); err != nil { return err diff --git a/daemon/daemon.go b/daemon/daemon.go index 50707fbc98..2aac521072 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -289,6 +289,8 @@ func (daemon *Daemon) Destroy(container *Container) error { if err := os.RemoveAll(container.root); err != nil { return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) } + selinux.FreeLxcContexts(container.ProcessLabel) + return nil } @@ -839,7 +841,7 @@ func (daemon *Daemon) Close() error { } func (daemon *Daemon) Mount(container *Container) error { - dir, err := daemon.driver.Get(container.ID, container.mountLabel) + dir, err := daemon.driver.Get(container.ID, container.MountLabel) if err != nil { return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) } diff --git a/daemonconfig/config.go b/daemonconfig/config.go index 87ac52224d..619bfe582f 100644 --- a/daemonconfig/config.go +++ b/daemonconfig/config.go @@ -47,7 +47,7 @@ func ConfigFromJob(job *engine.Job) *Config { InterContainerCommunication: job.GetenvBool("InterContainerCommunication"), GraphDriver: job.Getenv("GraphDriver"), ExecDriver: job.Getenv("ExecDriver"), - EnableSelinuxSupport: job.GetenvBool("SelinuxEnabled"), + EnableSelinuxSupport: job.GetenvBool("EnableSelinuxSupport"), } if dns := job.GetenvList("Dns"); dns != nil { config.Dns = dns diff --git a/docker/docker.go b/docker/docker.go index ce3c54dacd..7c366001b7 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -149,7 +149,7 @@ func main() { job.Setenv("GraphDriver", *flGraphDriver) job.Setenv("ExecDriver", *flExecDriver) job.SetenvInt("Mtu", *flMtu) - job.SetenvBool("SelinuxEnabled", *flSelinuxEnabled) + job.SetenvBool("EnableSelinuxSupport", *flSelinuxEnabled) if err := job.Run(); err != nil { log.Fatal(err) } diff --git a/pkg/label/label.go b/pkg/label/label.go index 38f026bc5a..434e1c5725 100644 --- a/pkg/label/label.go +++ b/pkg/label/label.go @@ -24,3 +24,7 @@ func GetPidCon(pid int) (string, error) { func Init() { } + +func ReserveLabel(label string) error { + return nil +} diff --git a/pkg/label/label_selinux.go b/pkg/label/label_selinux.go index 2f67ee458f..9361a7142c 100644 --- a/pkg/label/label_selinux.go +++ b/pkg/label/label_selinux.go @@ -75,3 +75,7 @@ func GetPidCon(pid int) (string, error) { func Init() { selinux.SelinuxEnabled() } + +func ReserveLabel(label string) { + selinux.ReserveLabel(label) +} diff --git a/pkg/selinux/selinux.go b/pkg/selinux/selinux.go index edabc4f7dd..422c39babd 100644 --- a/pkg/selinux/selinux.go +++ b/pkg/selinux/selinux.go @@ -204,6 +204,13 @@ func NewContext(scon string) SELinuxContext { return c } +func ReserveLabel(scon string) { + if len(scon) != 0 { + con := strings.SplitN(scon, ":", 4) + mcsAdd(con[3]) + } +} + func SelinuxGetEnforce() int { var enforce int @@ -229,8 +236,12 @@ func SelinuxGetEnforceMode() int { return Disabled } -func mcsAdd(mcs string) { +func mcsAdd(mcs string) error { + if mcsList[mcs] { + return fmt.Errorf("MCS Label already exists") + } mcsList[mcs] = true + return nil } func mcsDelete(mcs string) { @@ -283,15 +294,21 @@ func uniqMcs(catRange uint32) string { } } mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) - if mcsExists(mcs) { + if err := mcsAdd(mcs); err != nil { continue } - mcsAdd(mcs) break } return mcs } +func FreeLxcContexts(scon string) { + if len(scon) != 0 { + con := strings.SplitN(scon, ":", 4) + mcsDelete(con[3]) + } +} + func GetLxcContexts() (processLabel string, fileLabel string) { var ( val, key string @@ -344,7 +361,8 @@ func GetLxcContexts() (processLabel string, fileLabel string) { } exit: - mcs := IntToMcs(os.Getpid(), 1024) + // mcs := IntToMcs(os.Getpid(), 1024) + mcs := uniqMcs(1024) scon := NewContext(processLabel) scon["level"] = mcs processLabel = scon.Get() @@ -373,6 +391,8 @@ func CopyLevel(src, dest string) (string, error) { } scon := NewContext(src) tcon := NewContext(dest) + mcsDelete(tcon["level"]) + mcsAdd(scon["level"]) tcon["level"] = scon["level"] return tcon.Get(), nil } diff --git a/pkg/selinux/selinux_test.go b/pkg/selinux/selinux_test.go index fde6ab147d..9a3a5525e4 100644 --- a/pkg/selinux/selinux_test.go +++ b/pkg/selinux/selinux_test.go @@ -31,9 +31,11 @@ func TestSELinux(t *testing.T) { plabel, flabel = selinux.GetLxcContexts() t.Log(plabel) t.Log(flabel) + selinux.FreeLxcContexts(plabel) plabel, flabel = selinux.GetLxcContexts() t.Log(plabel) t.Log(flabel) + selinux.FreeLxcContexts(plabel) t.Log("getenforce ", selinux.SelinuxGetEnforce()) t.Log("getenforcemode ", selinux.SelinuxGetEnforceMode()) pid := os.Getpid() From 12934ef3a40d814cb307dfea0cc86124ec997593 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Fri, 25 Apr 2014 14:34:42 -0400 Subject: [PATCH 3/8] Fix SELinux errors caused by multi-threading Occasionally the selinux_test program will fail because we are setting file context based on the Process ID but not the TID. THis change will always use the TID to set SELinux labels. Docker-DCO-1.1-Signed-off-by: Daniel Walsh (github: rhatdan) Docker-DCO-1.1-Signed-off-by: Dan Walsh (github: crosbymichael) --- pkg/selinux/selinux.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/selinux/selinux.go b/pkg/selinux/selinux.go index 422c39babd..6cf7bd7104 100644 --- a/pkg/selinux/selinux.go +++ b/pkg/selinux/selinux.go @@ -146,15 +146,15 @@ func Setfilecon(path string, scon string) error { } func Setfscreatecon(scon string) error { - return writeCon("/proc/self/attr/fscreate", scon) + return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid()), scon) } func Getfscreatecon() (string, error) { - return readCon("/proc/self/attr/fscreate") + return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", system.Gettid())) } func getcon() (string, error) { - return readCon("/proc/self/attr/current") + return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", system.Gettid())) } func Getpidcon(pid int) (string, error) { From ae006493054e524ed35c08863f1713986fe0a22c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 28 Apr 2014 14:17:31 -0700 Subject: [PATCH 4/8] Update devicemapper to pass mount flag Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- daemon/graphdriver/devmapper/driver.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 558feef327..9f240d96e0 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -4,11 +4,12 @@ package devmapper import ( "fmt" - "github.com/dotcloud/docker/daemon/graphdriver" - "github.com/dotcloud/docker/utils" "io/ioutil" "os" "path" + + "github.com/dotcloud/docker/daemon/graphdriver" + "github.com/dotcloud/docker/utils" ) func init() { @@ -98,7 +99,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) { } // Mount the device - if err := d.DeviceSet.MountDevice(id, mp, ""); err != nil { + if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil { return "", err } From 46e05ed2d96efca9bdb466d20138fde1994769ba Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 28 Apr 2014 14:36:04 -0700 Subject: [PATCH 5/8] Update process labels to be set at create not start Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- daemon/container.go | 32 ++++++++++------------- daemon/daemon.go | 25 +++++++++++------- daemon/graphdriver/devmapper/deviceset.go | 9 +++---- pkg/label/label_selinux.go | 6 +++-- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index 2190869da0..17eaac7323 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -4,6 +4,16 @@ import ( "encoding/json" "errors" "fmt" + "io" + "io/ioutil" + "log" + "os" + "path" + "strings" + "sync" + "syscall" + "time" + "github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/daemon/execdriver" "github.com/dotcloud/docker/daemon/graphdriver" @@ -14,15 +24,6 @@ import ( "github.com/dotcloud/docker/pkg/label" "github.com/dotcloud/docker/runconfig" "github.com/dotcloud/docker/utils" - "io" - "io/ioutil" - "log" - "os" - "path" - "strings" - "sync" - "syscall" - "time" ) const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" @@ -124,7 +125,10 @@ func (container *Container) FromDisk() error { if err := json.Unmarshal(data, container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") { return err } - label.ReserveLabel(container.ProcessLabel) + + if err := label.ReserveLabel(container.ProcessLabel); err != nil { + return err + } return container.readHostConfig() } @@ -389,14 +393,6 @@ func (container *Container) Start() (err error) { return err } - process, mount, err := label.GenLabels("") - if err != nil { - return err - } - - container.MountLabel = mount - container.ProcessLabel = process - if err := container.Mount(); err != nil { return err } diff --git a/daemon/daemon.go b/daemon/daemon.go index 2aac521072..cdd1bb915f 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -3,6 +3,16 @@ package daemon import ( "container/list" "fmt" + "io" + "io/ioutil" + "log" + "os" + "path" + "regexp" + "strings" + "sync" + "time" + "github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/daemon/execdriver" "github.com/dotcloud/docker/daemon/execdriver/execdrivers" @@ -17,20 +27,12 @@ import ( "github.com/dotcloud/docker/graph" "github.com/dotcloud/docker/image" "github.com/dotcloud/docker/pkg/graphdb" + "github.com/dotcloud/docker/pkg/label" "github.com/dotcloud/docker/pkg/mount" "github.com/dotcloud/docker/pkg/selinux" "github.com/dotcloud/docker/pkg/sysinfo" "github.com/dotcloud/docker/runconfig" "github.com/dotcloud/docker/utils" - "io" - "io/ioutil" - "log" - "os" - "path" - "regexp" - "strings" - "sync" - "time" ) // Set the max depth to the aufs default that most @@ -535,6 +537,11 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, img *i ExecDriver: daemon.execDriver.Name(), } container.root = daemon.containerRoot(container.ID) + + if container.MountLabel, container.ProcessLabel, err = label.GenLabels(""); err != nil { + return nil, err + } + return container, nil } diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index a562210e55..a96331d812 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -6,8 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/dotcloud/docker/pkg/label" - "github.com/dotcloud/docker/utils" "io" "io/ioutil" "path" @@ -17,6 +15,9 @@ import ( "sync" "syscall" "time" + + "github.com/dotcloud/docker/pkg/label" + "github.com/dotcloud/docker/utils" ) var ( @@ -858,7 +859,6 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { defer devices.Unlock() if info.mountCount > 0 { - fmt.Printf("---> already mounted\n") if path != info.mountPath { return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path) } @@ -874,12 +874,9 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { var flags uintptr = sysMsMgcVal mountOptions := label.FormatMountLabel("discard", mountLabel) - fmt.Printf("-----> setting mount label %s\n", mountOptions) - err = sysMount(info.DevName(), path, "ext4", flags, mountOptions) if err != nil && err == sysEInval { mountOptions = label.FormatMountLabel("", mountLabel) - fmt.Printf("-----> setting mount label after error %s\n", mountOptions) err = sysMount(info.DevName(), path, "ext4", flags, mountOptions) } if err != nil { diff --git a/pkg/label/label_selinux.go b/pkg/label/label_selinux.go index 9361a7142c..926f7fffa8 100644 --- a/pkg/label/label_selinux.go +++ b/pkg/label/label_selinux.go @@ -4,8 +4,9 @@ package label import ( "fmt" - "github.com/dotcloud/docker/pkg/selinux" "strings" + + "github.com/dotcloud/docker/pkg/selinux" ) func GenLabels(options string) (string, string, error) { @@ -76,6 +77,7 @@ func Init() { selinux.SelinuxEnabled() } -func ReserveLabel(label string) { +func ReserveLabel(label string) error { selinux.ReserveLabel(label) + return nil } From 64d0f7e39b395a3fc52f441a53f188a19bd53cf3 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 29 Apr 2014 00:47:09 -0700 Subject: [PATCH 6/8] Add cli flag to docs for selinux support Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- docs/sources/reference/commandline/cli.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index ac589c01b2..75a5be33b6 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -60,6 +60,7 @@ expect an integer, and they can only be specified once. -d, --daemon=false: Enable daemon mode --dns=[]: Force docker to use specific DNS servers --dns-search=[]: Force Docker to use specific DNS search domains + --enable-selinux=false: Enable selinux support for running containers -g, --graph="/var/lib/docker": Path to use as the root of the docker runtime --icc=true: Enable inter-container communication --ip="0.0.0.0": Default IP address to use when binding container ports From 1a5ffef6c6ea8c5cc31c298bbdf6f7a29c60fbb8 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 29 Apr 2014 01:08:19 -0700 Subject: [PATCH 7/8] Do not return labels when in privileged mode Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- daemon/container.go | 21 ++++++++++++++++++--- daemon/daemon.go | 5 ++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/daemon/container.go b/daemon/container.go index 17eaac7323..5e4b72bf12 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -330,8 +330,8 @@ func populateCommand(c *Container, env []string) { en *execdriver.Network context = make(map[string][]string) ) - context["process_label"] = []string{c.ProcessLabel} - context["mount_label"] = []string{c.MountLabel} + context["process_label"] = []string{c.GetProcessLabel()} + context["mount_label"] = []string{c.GetMountLabel()} en = &execdriver.Network{ Mtu: c.daemon.config.Mtu, @@ -392,7 +392,6 @@ func (container *Container) Start() (err error) { if err := container.setupContainerDns(); err != nil { return err } - if err := container.Mount(); err != nil { return err } @@ -1192,3 +1191,19 @@ func (container *Container) allocatePort(eng *engine.Engine, port nat.Port, bind bindings[port] = binding return nil } + +func (container *Container) GetProcessLabel() string { + // even if we have a process label return "" if we are running + // in privileged mode + if container.hostConfig.Privileged { + return "" + } + return container.ProcessLabel +} + +func (container *Container) GetMountLabel() string { + if container.hostConfig.Privileged { + return "" + } + return container.MountLabel +} diff --git a/daemon/daemon.go b/daemon/daemon.go index cdd1bb915f..64a53989d0 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -538,10 +538,9 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, img *i } container.root = daemon.containerRoot(container.ID) - if container.MountLabel, container.ProcessLabel, err = label.GenLabels(""); err != nil { + if container.ProcessLabel, container.MountLabel, err = label.GenLabels(""); err != nil { return nil, err } - return container, nil } @@ -848,7 +847,7 @@ func (daemon *Daemon) Close() error { } func (daemon *Daemon) Mount(container *Container) error { - dir, err := daemon.driver.Get(container.ID, container.MountLabel) + dir, err := daemon.driver.Get(container.ID, container.GetMountLabel()) if err != nil { return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err) } From 0c7143b32386c62cccd529de69abf88df938757d Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 29 Apr 2014 03:41:44 -0700 Subject: [PATCH 8/8] Add mountlabel to dev Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- pkg/libcontainer/mount/init.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/libcontainer/mount/init.go b/pkg/libcontainer/mount/init.go index 06b2c82f56..735970cded 100644 --- a/pkg/libcontainer/mount/init.go +++ b/pkg/libcontainer/mount/init.go @@ -4,14 +4,15 @@ package mount import ( "fmt" + "os" + "path/filepath" + "syscall" + "github.com/dotcloud/docker/pkg/label" "github.com/dotcloud/docker/pkg/libcontainer" "github.com/dotcloud/docker/pkg/libcontainer/mount/nodes" "github.com/dotcloud/docker/pkg/libcontainer/security/restrict" "github.com/dotcloud/docker/pkg/system" - "os" - "path/filepath" - "syscall" ) // default mount point flags @@ -130,11 +131,12 @@ func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mo } if len(mounts.OfType("devtmpfs")) == 1 { - systemMounts = append(systemMounts, mount{source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: "mode=755"}) + systemMounts = append(systemMounts, mount{source: "tmpfs", path: filepath.Join(rootfs, "dev"), device: "tmpfs", flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, data: label.FormatMountLabel("mode=755", mountLabel)}) } systemMounts = append(systemMounts, mount{source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)}, - mount{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)}) + mount{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)}, + ) if len(mounts.OfType("sysfs")) == 1 { systemMounts = append(systemMounts, mount{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags})