diff --git a/libcontainer/container.go b/libcontainer/container.go index 7328f55..0ea8d37 100644 --- a/libcontainer/container.go +++ b/libcontainer/container.go @@ -11,19 +11,19 @@ type Context map[string]string // Container defines configuration options for how a // container is setup inside a directory and how a process should be executed type Container struct { - Hostname string `json:"hostname,omitempty"` // hostname - ReadonlyFs bool `json:"readonly_fs,omitempty"` // set the containers rootfs as readonly - NoPivotRoot bool `json:"no_pivot_root,omitempty"` // this can be enabled if you are running in ramdisk - User string `json:"user,omitempty"` // user to execute the process as - WorkingDir string `json:"working_dir,omitempty"` // current working directory - Env []string `json:"environment,omitempty"` // environment to set - Tty bool `json:"tty,omitempty"` // setup a proper tty or not - Namespaces map[string]bool `json:"namespaces,omitempty"` // namespaces to apply - CapabilitiesMask map[string]bool `json:"capabilities_mask,omitempty"` // capabilities to drop - Networks []*Network `json:"networks,omitempty"` // nil for host's network stack - Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups - Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux) - Mounts Mounts `json:"mounts,omitempty"` + Hostname string `json:"hostname,omitempty"` // hostname + ReadonlyFs bool `json:"readonly_fs,omitempty"` // set the containers rootfs as readonly + NoPivotRoot bool `json:"no_pivot_root,omitempty"` // this can be enabled if you are running in ramdisk + User string `json:"user,omitempty"` // user to execute the process as + WorkingDir string `json:"working_dir,omitempty"` // current working directory + Env []string `json:"environment,omitempty"` // environment to set + Tty bool `json:"tty,omitempty"` // setup a proper tty or not + Namespaces map[string]bool `json:"namespaces,omitempty"` // namespaces to apply + Capabilities []string `json:"capabilities,omitempty"` // capabilities given to the container + Networks []*Network `json:"networks,omitempty"` // nil for host's network stack + Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups + Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux) + Mounts Mounts `json:"mounts,omitempty"` } // Network defines configuration for a container's networking stack diff --git a/libcontainer/container.json b/libcontainer/container.json index 33d7960..07950fe 100644 --- a/libcontainer/container.json +++ b/libcontainer/container.json @@ -24,24 +24,9 @@ "mtu": 1500 } ], - "capabilities_mask": { - "SYSLOG": false, - "MKNOD": true, - "NET_ADMIN": false, - "MAC_ADMIN": false, - "MAC_OVERRIDE": false, - "AUDIT_CONTROL": false, - "AUDIT_WRITE": false, - "SYS_TTY_CONFIG": false, - "SETPCAP": false, - "SYS_MODULE": false, - "SYS_RAWIO": false, - "SYS_PACCT": false, - "SYS_ADMIN": false, - "SYS_NICE": false, - "SYS_RESOURCE": false, - "SYS_TIME": false - }, + "capabilities": [ + "MKNOD" + ], "cgroups": { "name": "docker-koye", "parent": "docker" diff --git a/libcontainer/container_test.go b/libcontainer/container_test.go index c02385a..b3f2407 100644 --- a/libcontainer/container_test.go +++ b/libcontainer/container_test.go @@ -6,6 +6,16 @@ import ( "testing" ) +// Checks whether the expected capability is specified in the capabilities. +func hasCapability(expected string, capabilities []string) bool { + for _, capability := range capabilities { + if capability == expected { + return true + } + } + return false +} + func TestContainerJsonFormat(t *testing.T) { f, err := os.Open("container.json") if err != nil { @@ -37,22 +47,17 @@ func TestContainerJsonFormat(t *testing.T) { t.Fail() } - if _, exists := container.CapabilitiesMask["SYS_ADMIN"]; !exists { - t.Log("capabilities mask should contain SYS_ADMIN") - t.Fail() - } - - if container.CapabilitiesMask["SYS_ADMIN"] { + if hasCapability("SYS_ADMIN", container.Capabilities) { t.Log("SYS_ADMIN should not be enabled in capabilities mask") t.Fail() } - if !container.CapabilitiesMask["MKNOD"] { + if !hasCapability("MKNOD", container.Capabilities) { t.Log("MKNOD should be enabled in capabilities mask") t.Fail() } - if container.CapabilitiesMask["SYS_CHROOT"] { + if hasCapability("SYS_CHROOT", container.Capabilities) { t.Log("capabilities mask should not contain SYS_CHROOT") t.Fail() } diff --git a/libcontainer/security/capabilities/capabilities.go b/libcontainer/security/capabilities/capabilities.go index 107417a..ba72070 100644 --- a/libcontainer/security/capabilities/capabilities.go +++ b/libcontainer/security/capabilities/capabilities.go @@ -26,14 +26,12 @@ func DropCapabilities(container *libcontainer.Container) error { return nil } -// getCapabilitiesMask returns the capabilities that should not be dropped by the container. +// getEnabledCapabilities returns the capabilities that should not be dropped by the container. func getEnabledCapabilities(container *libcontainer.Container) []capability.Cap { keep := []capability.Cap{} - for key, enabled := range container.CapabilitiesMask { - if enabled { - if c := libcontainer.GetCapability(key); c != nil { - keep = append(keep, c.Value) - } + for _, capability := range container.Capabilities { + if c := libcontainer.GetCapability(capability); c != nil { + keep = append(keep, c.Value) } } return keep diff --git a/libcontainer/types.go b/libcontainer/types.go index 4c8f60c..ed5cce4 100644 --- a/libcontainer/types.go +++ b/libcontainer/types.go @@ -123,6 +123,14 @@ func GetCapability(key string) *Capability { return nil } +func GetAllCapabilities() []string { + output := make([]string, len(capabilityList)) + for i, capability := range capabilityList { + output[i] = capability.String() + } + return output +} + // Contains returns true if the specified Capability is // in the slice func (c Capabilities) Contains(capp string) bool {