diff --git a/execdriver/native/default_template.go b/execdriver/native/default_template.go index 7426e678e8..cc464631cd 100644 --- a/execdriver/native/default_template.go +++ b/execdriver/native/default_template.go @@ -48,28 +48,29 @@ func createContainer(c *execdriver.Command) *libcontainer.Container { func getDefaultTemplate() *libcontainer.Container { return &libcontainer.Container{ Capabilities: libcontainer.Capabilities{ - libcontainer.CAP_SETPCAP, - libcontainer.CAP_SYS_MODULE, - libcontainer.CAP_SYS_RAWIO, - libcontainer.CAP_SYS_PACCT, - libcontainer.CAP_SYS_ADMIN, - libcontainer.CAP_SYS_NICE, - libcontainer.CAP_SYS_RESOURCE, - libcontainer.CAP_SYS_TIME, - libcontainer.CAP_SYS_TTY_CONFIG, - libcontainer.CAP_MKNOD, - libcontainer.CAP_AUDIT_WRITE, - libcontainer.CAP_AUDIT_CONTROL, - libcontainer.CAP_MAC_ADMIN, - libcontainer.CAP_MAC_OVERRIDE, - libcontainer.CAP_NET_ADMIN, + libcontainer.GetCapability("SETPCAP"), + libcontainer.GetCapability("SYS_MODULE"), + libcontainer.GetCapability("SYS_RAWIO"), + libcontainer.GetCapability("SYS_PACCT"), + libcontainer.GetCapability("SYS_ADMIN"), + libcontainer.GetCapability("SYS_NICE"), + libcontainer.GetCapability("SYS_RESOURCE"), + libcontainer.GetCapability("SYS_TIME"), + libcontainer.GetCapability("SYS_TTY_CONFIG"), + libcontainer.GetCapability("MKNOD"), + libcontainer.GetCapability("AUDIT_WRITE"), + libcontainer.GetCapability("AUDIT_CONTROL"), + libcontainer.GetCapability("MAC_OVERRIDE"), + libcontainer.GetCapability("MAC_ADMIN"), + libcontainer.GetCapability("NET_ADMIN"), }, Namespaces: libcontainer.Namespaces{ - libcontainer.CLONE_NEWIPC, - libcontainer.CLONE_NEWNET, - libcontainer.CLONE_NEWNS, - libcontainer.CLONE_NEWPID, - libcontainer.CLONE_NEWUTS, + libcontainer.GetNamespace("NEWNS"), + libcontainer.GetNamespace("NEWUTS"), + libcontainer.GetNamespace("NEWIPC"), + libcontainer.GetNamespace("NEWUSER"), + libcontainer.GetNamespace("NEWPID"), + libcontainer.GetNamespace("NEWNET"), }, Cgroups: &cgroups.Cgroup{ Parent: "docker", diff --git a/pkg/libcontainer/capabilities/capabilities.go b/pkg/libcontainer/capabilities/capabilities.go index 65fd455c26..3c6d752496 100644 --- a/pkg/libcontainer/capabilities/capabilities.go +++ b/pkg/libcontainer/capabilities/capabilities.go @@ -6,24 +6,6 @@ import ( "os" ) -var capMap = map[libcontainer.Capability]capability.Cap{ - libcontainer.CAP_SETPCAP: capability.CAP_SETPCAP, - libcontainer.CAP_SYS_MODULE: capability.CAP_SYS_MODULE, - libcontainer.CAP_SYS_RAWIO: capability.CAP_SYS_RAWIO, - libcontainer.CAP_SYS_PACCT: capability.CAP_SYS_PACCT, - libcontainer.CAP_SYS_ADMIN: capability.CAP_SYS_ADMIN, - libcontainer.CAP_SYS_NICE: capability.CAP_SYS_NICE, - libcontainer.CAP_SYS_RESOURCE: capability.CAP_SYS_RESOURCE, - libcontainer.CAP_SYS_TIME: capability.CAP_SYS_TIME, - libcontainer.CAP_SYS_TTY_CONFIG: capability.CAP_SYS_TTY_CONFIG, - libcontainer.CAP_MKNOD: capability.CAP_MKNOD, - libcontainer.CAP_AUDIT_WRITE: capability.CAP_AUDIT_WRITE, - libcontainer.CAP_AUDIT_CONTROL: capability.CAP_AUDIT_CONTROL, - libcontainer.CAP_MAC_OVERRIDE: capability.CAP_MAC_OVERRIDE, - libcontainer.CAP_MAC_ADMIN: capability.CAP_MAC_ADMIN, - libcontainer.CAP_NET_ADMIN: capability.CAP_NET_ADMIN, -} - // DropCapabilities drops capabilities for the current process based // on the container's configuration. func DropCapabilities(container *libcontainer.Container) error { @@ -45,7 +27,7 @@ func DropCapabilities(container *libcontainer.Container) error { func getCapabilities(container *libcontainer.Container) []capability.Cap { drop := []capability.Cap{} for _, c := range container.Capabilities { - drop = append(drop, capMap[c]) + drop = append(drop, c.Value) } return drop } diff --git a/pkg/libcontainer/nsinit/execin.go b/pkg/libcontainer/nsinit/execin.go index 463196c7c0..306250cf9b 100644 --- a/pkg/libcontainer/nsinit/execin.go +++ b/pkg/libcontainer/nsinit/execin.go @@ -14,7 +14,7 @@ import ( // ExecIn uses an existing pid and joins the pid's namespaces with the new command. func (ns *linuxNs) ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) { for _, ns := range container.Namespaces { - if err := system.Unshare(namespaceMap[ns]); err != nil { + if err := system.Unshare(ns.Value); err != nil { return -1, err } } @@ -42,8 +42,7 @@ func (ns *linuxNs) ExecIn(container *libcontainer.Container, nspid int, args []s // if the container has a new pid and mount namespace we need to // remount proc and sys to pick up the changes - if container.Namespaces.Contains(libcontainer.CLONE_NEWNS) && - container.Namespaces.Contains(libcontainer.CLONE_NEWPID) { + if container.Namespaces.Contains("CLONE_NEWNS") && container.Namespaces.Contains("CLONE_NEWPID") { pid, err := system.Fork() if err != nil { return -1, err @@ -84,7 +83,7 @@ dropAndExec: func (ns *linuxNs) getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) { fds := make([]uintptr, len(container.Namespaces)) for i, ns := range container.Namespaces { - f, err := os.OpenFile(filepath.Join("/proc/", strconv.Itoa(pid), "ns", namespaceFileMap[ns]), os.O_RDONLY, 0) + f, err := os.OpenFile(filepath.Join("/proc/", strconv.Itoa(pid), "ns", ns.File), os.O_RDONLY, 0) if err != nil { return fds, err } diff --git a/pkg/libcontainer/nsinit/ns_linux.go b/pkg/libcontainer/nsinit/ns_linux.go index 58af24798f..ab6322e75c 100644 --- a/pkg/libcontainer/nsinit/ns_linux.go +++ b/pkg/libcontainer/nsinit/ns_linux.go @@ -2,35 +2,13 @@ package nsinit import ( "github.com/dotcloud/docker/pkg/libcontainer" - "syscall" ) -var namespaceMap = map[libcontainer.Namespace]int{ - libcontainer.CLONE_NEWNS: syscall.CLONE_NEWNS, - libcontainer.CLONE_NEWUTS: syscall.CLONE_NEWUTS, - libcontainer.CLONE_NEWIPC: syscall.CLONE_NEWIPC, - libcontainer.CLONE_NEWUSER: syscall.CLONE_NEWUSER, - libcontainer.CLONE_NEWPID: syscall.CLONE_NEWPID, - libcontainer.CLONE_NEWNET: syscall.CLONE_NEWNET, -} - -// namespaceFileMap is used to convert the libcontainer types -// into the names of the files located in /proc//ns/* for -// each namespace -var namespaceFileMap = map[libcontainer.Namespace]string{ - libcontainer.CLONE_NEWNS: "mnt", - libcontainer.CLONE_NEWUTS: "uts", - libcontainer.CLONE_NEWIPC: "ipc", - libcontainer.CLONE_NEWUSER: "user", - libcontainer.CLONE_NEWPID: "pid", - libcontainer.CLONE_NEWNET: "net", -} - // getNamespaceFlags parses the container's Namespaces options to set the correct // flags on clone, unshare, and setns func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) { for _, ns := range namespaces { - flag |= namespaceMap[ns] + flag |= ns.Value } return flag } diff --git a/pkg/libcontainer/types.go b/pkg/libcontainer/types.go index bb54ff5130..cb64db1f29 100644 --- a/pkg/libcontainer/types.go +++ b/pkg/libcontainer/types.go @@ -1,58 +1,131 @@ package libcontainer -// These constants are defined as string types so that -// it is clear when adding the configuration in config files -// instead of using ints or other types -const ( - CAP_SETPCAP Capability = "SETPCAP" - CAP_SYS_MODULE Capability = "SYS_MODULE" - CAP_SYS_RAWIO Capability = "SYS_RAWIO" - CAP_SYS_PACCT Capability = "SYS_PACCT" - CAP_SYS_ADMIN Capability = "SYS_ADMIN" - CAP_SYS_NICE Capability = "SYS_NICE" - CAP_SYS_RESOURCE Capability = "SYS_RESOURCE" - CAP_SYS_TIME Capability = "SYS_TIME" - CAP_SYS_TTY_CONFIG Capability = "SYS_TTY_CONFIG" - CAP_MKNOD Capability = "MKNOD" - CAP_AUDIT_WRITE Capability = "AUDIT_WRITE" - CAP_AUDIT_CONTROL Capability = "AUDIT_CONTROL" - CAP_MAC_OVERRIDE Capability = "MAC_OVERRIDE" - CAP_MAC_ADMIN Capability = "MAC_ADMIN" - CAP_NET_ADMIN Capability = "NET_ADMIN" +import ( + "encoding/json" + "errors" + "github.com/syndtr/gocapability/capability" + "os" + "syscall" +) - CLONE_NEWNS Namespace = "NEWNS" // mount - CLONE_NEWUTS Namespace = "NEWUTS" // utsname - CLONE_NEWIPC Namespace = "NEWIPC" // ipc - CLONE_NEWUSER Namespace = "NEWUSER" // user - CLONE_NEWPID Namespace = "NEWPID" // pid - CLONE_NEWNET Namespace = "NEWNET" // network +var ( + ErrUnkownNamespace error = errors.New("Unkown namespace") +) + +// namespaceList is used to convert the libcontainer types +// into the names of the files located in /proc//ns/* for +// each namespace +var ( + namespaceList = Namespaces{ + {Key: "NEWNS", Value: syscall.CLONE_NEWNS, File: "mnt"}, + {Key: "NEWUTS", Value: syscall.CLONE_NEWUTS, File: "uts"}, + {Key: "NEWIPC", Value: syscall.CLONE_NEWIPC, File: "ipc"}, + {Key: "NEWUSER", Value: syscall.CLONE_NEWUSER, File: "user"}, + {Key: "NEWPID", Value: syscall.CLONE_NEWPID, File: "pid"}, + {Key: "NEWNET", Value: syscall.CLONE_NEWNET, File: "net"}, + } + capabilityList = Capabilities{ + {Key: "SETPCAP", Value: capability.CAP_SETPCAP}, + {Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE}, + {Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO}, + {Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT}, + {Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN}, + {Key: "SYS_NICE", Value: capability.CAP_SYS_NICE}, + {Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE}, + {Key: "SYS_TIME", Value: capability.CAP_SYS_TIME}, + {Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG}, + {Key: "MKNOD", Value: capability.CAP_MKNOD}, + {Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE}, + {Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL}, + {Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE}, + {Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN}, + {Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN}, + } ) type ( - Namespace string - Namespaces []Namespace - Capability string - Capabilities []Capability + Namespace struct { + Key string + Value int + File string + } + Namespaces []*Namespace ) +func (ns *Namespace) MarshalJSON() ([]byte, error) { + return json.Marshal(ns.Key) +} + +func (ns *Namespace) UnmarshalJSON(src []byte) error { + var nsName string + if err := json.Unmarshal(src, &nsName); err != nil { + return err + } + ret := GetNamespace(nsName) + if ret == nil { + return ErrUnkownNamespace + } + *ns = *ret + return nil +} + +func GetNamespace(key string) *Namespace { + for _, ns := range namespaceList { + if ns.Key == key { + return ns + } + } + if os.Getenv("DEBUG") != "" { + panic("Unreachable: Namespace not found") + } + return nil +} + // Contains returns true if the specified Namespace is // in the slice -func (n Namespaces) Contains(ns Namespace) bool { - for _, nns := range n { - if nns == ns { - return true +func (n Namespaces) Contains(ns string) bool { + return GetNamespace(ns) != nil +} + +type ( + Capability struct { + Key string + Value capability.Cap + } + Capabilities []*Capability +) + +func (ns *Capability) MarshalJSON() ([]byte, error) { + return json.Marshal(ns.Key) +} + +func (ns *Capability) UnmarshalJSON(src []byte) error { + var capName string + if err := json.Unmarshal(src, &capName); err != nil { + return err + } + ret := GetCapability(capName) + if ret == nil { + return ErrUnkownNamespace + } + *ns = *ret + return nil +} + +func GetCapability(key string) *Capability { + for _, capp := range capabilityList { + if capp.Key == key { + return capp } } - return false + if os.Getenv("DEBUG") != "" { + panic("Unreachable: Namespace not found") + } + return nil } // Contains returns true if the specified Capability is // in the slice -func (c Capabilities) Contains(capp Capability) bool { - for _, cc := range c { - if cc == capp { - return true - } - } - return false +func (c Capabilities) Contains(capp string) bool { + return GetCapability(capp) != nil }