From c2e460fee5ff74d7bc381972599f22e266567979 Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Thu, 22 Jun 2017 15:13:39 -0600 Subject: [PATCH] check that caps are valid Rather than build the image and have something weird happen, let's check that the capabilities specified are actually valid capabilities. Signed-off-by: Tycho Andersen --- src/moby/config.go | 100 ++++++++++++++++++++++++---------------- src/moby/config_test.go | 45 ++++++++++++++---- 2 files changed, 95 insertions(+), 50 deletions(-) diff --git a/src/moby/config.go b/src/moby/config.go index 6e37f5b54..b74303cd5 100644 --- a/src/moby/config.go +++ b/src/moby/config.go @@ -420,6 +420,47 @@ func assignStringEmpty4(v1, v2, v3, v4 string) string { return v1 } +var allCaps = []string{ + "CAP_AUDIT_CONTROL", + "CAP_AUDIT_READ", + "CAP_AUDIT_WRITE", + "CAP_BLOCK_SUSPEND", + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_DAC_READ_SEARCH", + "CAP_FOWNER", + "CAP_FSETID", + "CAP_IPC_LOCK", + "CAP_IPC_OWNER", + "CAP_KILL", + "CAP_LEASE", + "CAP_LINUX_IMMUTABLE", + "CAP_MAC_ADMIN", + "CAP_MAC_OVERRIDE", + "CAP_MKNOD", + "CAP_NET_ADMIN", + "CAP_NET_BIND_SERVICE", + "CAP_NET_BROADCAST", + "CAP_NET_RAW", + "CAP_SETFCAP", + "CAP_SETGID", + "CAP_SETPCAP", + "CAP_SETUID", + "CAP_SYSLOG", + "CAP_SYS_ADMIN", + "CAP_SYS_BOOT", + "CAP_SYS_CHROOT", + "CAP_SYS_MODULE", + "CAP_SYS_NICE", + "CAP_SYS_PACCT", + "CAP_SYS_PTRACE", + "CAP_SYS_RAWIO", + "CAP_SYS_RESOURCE", + "CAP_SYS_TIME", + "CAP_SYS_TTY_CONFIG", + "CAP_WAKE_ALARM", +} + // ConfigInspectToOCI converts a config and the output of image inspect to an OCI config func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect) (specs.Spec, error) { oci := specs.Spec{} @@ -579,51 +620,30 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect) (specs.Spec, err // TODO user, cgroup namespaces caps := assignStrings(label.Capabilities, yaml.Capabilities) + for _, capability := range caps { + if capability == "none" || capability == "all" { + continue + } + + found := false + for _, ac := range allCaps { + if ac == capability { + found = true + break + } + } + + if !found { + return oci, fmt.Errorf("unknown capability: %s", capability) + } + } + if len(caps) == 1 { switch cap := strings.ToLower(caps[0]); cap { case "none": caps = []string{} case "all": - caps = []string{ - "CAP_AUDIT_CONTROL", - "CAP_AUDIT_READ", - "CAP_AUDIT_WRITE", - "CAP_BLOCK_SUSPEND", - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_DAC_READ_SEARCH", - "CAP_FOWNER", - "CAP_FSETID", - "CAP_IPC_LOCK", - "CAP_IPC_OWNER", - "CAP_KILL", - "CAP_LEASE", - "CAP_LINUX_IMMUTABLE", - "CAP_MAC_ADMIN", - "CAP_MAC_OVERRIDE", - "CAP_MKNOD", - "CAP_NET_ADMIN", - "CAP_NET_BIND_SERVICE", - "CAP_NET_BROADCAST", - "CAP_NET_RAW", - "CAP_SETFCAP", - "CAP_SETGID", - "CAP_SETPCAP", - "CAP_SETUID", - "CAP_SYSLOG", - "CAP_SYS_ADMIN", - "CAP_SYS_BOOT", - "CAP_SYS_CHROOT", - "CAP_SYS_MODULE", - "CAP_SYS_NICE", - "CAP_SYS_PACCT", - "CAP_SYS_PTRACE", - "CAP_SYS_RAWIO", - "CAP_SYS_RESOURCE", - "CAP_SYS_TIME", - "CAP_SYS_TTY_CONFIG", - "CAP_WAKE_ALARM", - } + caps = allCaps[:] } } diff --git a/src/moby/config_test.go b/src/moby/config_test.go index 498ca4213..bbd963a5d 100644 --- a/src/moby/config_test.go +++ b/src/moby/config_test.go @@ -9,6 +9,21 @@ import ( "github.com/docker/docker/api/types/container" ) +func setupInspect(t *testing.T, label Image) types.ImageInspect { + var inspect types.ImageInspect + var config container.Config + + labelJSON, err := json.Marshal(label) + if err != nil { + t.Error(err) + } + config.Labels = map[string]string{"org.mobyproject.config": string(labelJSON)} + + inspect.Config = &config + + return inspect +} + func TestOverrides(t *testing.T) { var yamlCaps = []string{"CAP_SYS_ADMIN"} @@ -25,16 +40,7 @@ func TestOverrides(t *testing.T) { Cwd: "/label/directory", } - var inspect types.ImageInspect - var config container.Config - - labelJSON, err := json.Marshal(label) - if err != nil { - t.Error(err) - } - config.Labels = map[string]string{"org.mobyproject.config": string(labelJSON)} - - inspect.Config = &config + inspect := setupInspect(t, label) oci, err := ConfigInspectToOCI(yaml, inspect) if err != nil { @@ -48,3 +54,22 @@ func TestOverrides(t *testing.T) { t.Error("Expected label Cwd to be applied, got", oci.Process.Cwd) } } + +func TestInvalidCap(t *testing.T) { + yaml := Image{ + Name: "test", + Image: "testimage", + } + + labelCaps := []string{"NOT_A_CAP"} + var label = Image{ + Capabilities: &labelCaps, + } + + inspect := setupInspect(t, label) + + _, err := ConfigInspectToOCI(yaml, inspect) + if err == nil { + t.Error("expected error, got valid OCI config") + } +}