diff --git a/daemon/execdriver/lxc/lxc_template.go b/daemon/execdriver/lxc/lxc_template.go index 5f0294ea18..c717cbca2b 100644 --- a/daemon/execdriver/lxc/lxc_template.go +++ b/daemon/execdriver/lxc/lxc_template.go @@ -1,12 +1,17 @@ package lxc import ( - "github.com/docker/docker/daemon/execdriver" - nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" - "github.com/docker/libcontainer/label" + "fmt" "os" "strings" "text/template" + + log "github.com/Sirupsen/logrus" + "github.com/docker/docker/daemon/execdriver" + nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" + "github.com/docker/docker/utils" + "github.com/docker/libcontainer/label" + "github.com/docker/libcontainer/security/capabilities" ) const LxcTemplate = ` @@ -126,9 +131,17 @@ lxc.utsname = {{getHostname .ProcessConfig.Env}} {{if .ProcessConfig.Privileged}} # No cap values are needed, as lxc is starting in privileged mode {{else}} -{{range $value := keepCapabilities .CapAdd .CapDrop}} -lxc.cap.keep = {{$value}} -{{end}} + {{ with keepCapabilities .CapAdd .CapDrop }} + {{range .}} +lxc.cap.keep = {{.}} + {{end}} + {{else}} + {{ with dropList .CapDrop }} + {{range .}} +lxc.cap.drop = {{.}} + {{end}} + {{end}} + {{end}} {{end}} {{end}} ` @@ -141,17 +154,39 @@ func escapeFstabSpaces(field string) string { return strings.Replace(field, " ", "\\040", -1) } -func keepCapabilities(adds []string, drops []string) []string { +func keepCapabilities(adds []string, drops []string) ([]string, error) { container := nativeTemplate.New() + log.Debugf("adds %s drops %s\n", adds, drops) caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) + if err != nil { + return nil, err + } var newCaps []string for _, cap := range caps { - newCaps = append(newCaps, strings.ToLower(cap)) + log.Debugf("cap %s\n", cap) + realCap := capabilities.GetCapability(cap) + numCap := fmt.Sprintf("%d", realCap.Value) + newCaps = append(newCaps, numCap) } - if err != nil { - return []string{} + + return newCaps, nil +} + +func dropList(drops []string) ([]string, error) { + if utils.StringsContainsNoCase(drops, "all") { + var newCaps []string + for _, cap := range capabilities.GetAllCapabilities() { + log.Debugf("drop cap %s\n", cap) + realCap := capabilities.GetCapability(cap) + if realCap == nil { + return nil, fmt.Errorf("Invalid capability '%s'", cap) + } + numCap := fmt.Sprintf("%d", realCap.Value) + newCaps = append(newCaps, numCap) + } + return newCaps, nil } - return newCaps + return []string{}, nil } func isDirectory(source string) string { @@ -206,6 +241,7 @@ func init() { "formatMountLabel": label.FormatMountLabel, "isDirectory": isDirectory, "keepCapabilities": keepCapabilities, + "dropList": dropList, "getHostname": getHostname, } LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) diff --git a/daemon/execdriver/lxc/lxc_template_unit_test.go b/daemon/execdriver/lxc/lxc_template_unit_test.go index f1410db77a..e072f8dbb4 100644 --- a/daemon/execdriver/lxc/lxc_template_unit_test.go +++ b/daemon/execdriver/lxc/lxc_template_unit_test.go @@ -5,6 +5,11 @@ package lxc import ( "bufio" "fmt" + "github.com/docker/docker/daemon/execdriver" + nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" + "github.com/docker/libcontainer/devices" + "github.com/docker/libcontainer/security/capabilities" + "github.com/syndtr/gocapability/capability" "io/ioutil" "math/rand" "os" @@ -12,10 +17,6 @@ import ( "strings" "testing" "time" - - "github.com/docker/docker/daemon/execdriver" - nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" - "github.com/docker/libcontainer/devices" ) func TestLXCConfig(t *testing.T) { @@ -292,13 +293,15 @@ func TestCustomLxcConfigMisc(t *testing.T) { grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") container := nativeTemplate.New() for _, cap := range container.Capabilities { - cap = strings.ToLower(cap) - if cap != "mknod" && cap != "kill" { - grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", cap)) + realCap := capabilities.GetCapability(cap) + numCap := fmt.Sprintf("%d", realCap.Value) + if cap != "MKNOD" && cap != "KILL" { + grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) } } - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = kill"), true) - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = mknod"), true) + + grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) + grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) } func TestCustomLxcConfigMiscOverride(t *testing.T) { @@ -333,8 +336,8 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) { }, }, ProcessConfig: processConfig, - CapAdd: []string{"net_admin", "syslog"}, - CapDrop: []string{"kill", "mknod"}, + CapAdd: []string{"NET_ADMIN", "SYSLOG"}, + CapDrop: []string{"KILL", "MKNOD"}, } p, err := driver.generateLXCConfig(command) @@ -354,11 +357,12 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) { grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") container := nativeTemplate.New() for _, cap := range container.Capabilities { - cap = strings.ToLower(cap) - if cap != "mknod" && cap != "kill" { - grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", cap)) + realCap := capabilities.GetCapability(cap) + numCap := fmt.Sprintf("%d", realCap.Value) + if cap != "MKNOD" && cap != "KILL" { + grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) } } - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = kill"), true) - grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = mknod"), true) + grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) + grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 30acd9e1c4..21bd4fa725 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -986,7 +986,7 @@ func TestRunCapDropCannotMknodLowerCase(t *testing.T) { } func TestRunCapDropALLCannotMknod(t *testing.T) { - cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") + cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") out, _, err := runCommandWithOutput(cmd) if err == nil { t.Fatal(err, out) @@ -1000,8 +1000,8 @@ func TestRunCapDropALLCannotMknod(t *testing.T) { logDone("run - test --cap-drop=ALL cannot mknod") } -func TestRunCapDropALLAddMknodCannotMknod(t *testing.T) { - cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") +func TestRunCapDropALLAddMknodCanMknod(t *testing.T) { + cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok") out, _, err := runCommandWithOutput(cmd) if err != nil { t.Fatal(err, out)