Merge pull request #5448 from crosbymichael/selinux-defaults

Add selinux label support for processes and mount
This commit is contained in:
Guillaume J. Charmes 2014-04-30 14:14:39 -07:00
commit 2a711d16e0
26 changed files with 240 additions and 167 deletions

View file

@ -4,15 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/daemon/execdriver"
"github.com/dotcloud/docker/daemon/graphdriver"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/image"
"github.com/dotcloud/docker/links"
"github.com/dotcloud/docker/nat"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
"log"
@ -22,6 +13,17 @@ import (
"sync"
"syscall"
"time"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/daemon/execdriver"
"github.com/dotcloud/docker/daemon/graphdriver"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/image"
"github.com/dotcloud/docker/links"
"github.com/dotcloud/docker/nat"
"github.com/dotcloud/docker/pkg/label"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/utils"
)
const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
@ -64,7 +66,8 @@ type Container struct {
stdin io.ReadCloser
stdinPipe io.WriteCloser
daemon *Daemon
daemon *Daemon
MountLabel, ProcessLabel string
waitLock chan struct{}
Volumes map[string]string
@ -122,6 +125,10 @@ func (container *Container) FromDisk() error {
if err := json.Unmarshal(data, container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
return err
}
if err := label.ReserveLabel(container.ProcessLabel); err != nil {
return err
}
return container.readHostConfig()
}
@ -320,9 +327,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.GetProcessLabel()}
context["mount_label"] = []string{c.GetMountLabel()}
en = &execdriver.Network{
Mtu: c.daemon.config.Mtu,
@ -340,7 +349,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 +367,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}
@ -1182,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
}

View file

@ -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
@ -289,6 +291,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
}
@ -533,6 +537,10 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, img *i
ExecDriver: daemon.execDriver.Name(),
}
container.root = daemon.containerRoot(container.ID)
if container.ProcessLabel, container.MountLabel, err = label.GenLabels(""); err != nil {
return nil, err
}
return container, nil
}
@ -543,10 +551,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 +564,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 +678,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 +847,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.GetMountLabel())
if err != nil {
return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
}
@ -862,12 +869,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 +892,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)
}

View file

@ -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
}

View file

@ -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) {

View file

@ -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)
}

View file

@ -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
}
}

View file

@ -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 {

View file

@ -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 (
@ -845,7 +846,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
@ -875,7 +876,7 @@ func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) erro
mountOptions := label.FormatMountLabel("discard", mountLabel)
err = sysMount(info.DevName(), path, "ext4", flags, mountOptions)
if err != nil && err == sysEInval {
mountOptions = label.FormatMountLabel(mountLabel, "")
mountOptions = label.FormatMountLabel("", mountLabel)
err = sysMount(info.DevName(), path, "ext4", flags, mountOptions)
}
if err != nil {

View file

@ -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() {
@ -60,7 +61,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 +90,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
@ -98,7 +99,7 @@ func (d *Driver) Get(id 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
}

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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)
}

View file

@ -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("EnableSelinuxSupport"),
}
if dns := job.GetenvList("Dns"); dns != nil {
config.Dns = dns

View file

@ -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("EnableSelinuxSupport", *flSelinuxEnabled)
if err := job.Run(); err != nil {
log.Fatal(err)
}

View file

@ -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

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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")
}
}

View file

@ -24,3 +24,7 @@ func GetPidCon(pid int) (string, error) {
func Init() {
}
func ReserveLabel(label string) error {
return nil
}

View file

@ -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) {
@ -32,13 +33,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
@ -75,3 +76,8 @@ func GetPidCon(pid int) (string, error) {
func Init() {
selinux.SelinuxEnabled()
}
func ReserveLabel(label string) error {
selinux.ReserveLabel(label)
return nil
}

View file

@ -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})

View file

@ -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)

View file

@ -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) {
@ -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
}

View file

@ -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()