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 <dwalsh@redhat.com> (github: rhatdan)
Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: crosbymichael)
This commit is contained in:
Dan Walsh 2014-04-21 17:09:26 -04:00 коммит произвёл Michael Crosby
Родитель f0e6e135a8
Коммит b7942ec2ca
8 изменённых файлов: 50 добавлений и 14 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -75,3 +75,7 @@ func GetPidCon(pid int) (string, error) {
func Init() {
selinux.SelinuxEnabled()
}
func ReserveLabel(label string) {
selinux.ReserveLabel(label)
}

Просмотреть файл

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

Просмотреть файл

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