diff --git a/config.go b/config.go index 94c2bd981..bf5236555 100644 --- a/config.go +++ b/config.go @@ -10,11 +10,51 @@ type MountConfig mount.MountConfig type Network network.Network +type NamespaceType string + +const ( + NEWNET NamespaceType = "NEWNET" + NEWPID NamespaceType = "NEWPID" + NEWNS NamespaceType = "NEWNS" + NEWUTS NamespaceType = "NEWUTS" + NEWIPC NamespaceType = "NEWIPC" + NEWUSER NamespaceType = "NEWUSER" +) + // Namespace defines configuration for each namespace. It specifies an // alternate path that is able to be joined via setns. type Namespace struct { - Name string `json:"name"` - Path string `json:"path,omitempty"` + Type NamespaceType `json:"type"` + Path string `json:"path,omitempty"` +} + +type Namespaces []Namespace + +func (n Namespaces) Remove(t NamespaceType) bool { + i := n.index(t) + if i == -1 { + return false + } + n = append(n[:i], n[i+1:]...) + return true +} + +func (n Namespaces) Add(t NamespaceType, path string) { + i := n.index(t) + if i == -1 { + n = append(n, Namespace{Type: t, Path: path}) + return + } + n[i].Path = path +} + +func (n Namespaces) index(t NamespaceType) int { + for i, ns := range n { + if ns.Type == t { + return i + } + } + return -1 } // Config defines configuration options for executing a process inside a contained environment. @@ -45,7 +85,7 @@ type Config struct { // Namespaces specifies the container's namespaces that it should setup when cloning the init process // If a namespace is not provided that namespace is shared from the container's parent process - Namespaces []Namespace `json:"namespaces,omitempty"` + Namespaces Namespaces `json:"namespaces,omitempty"` // Capabilities specify the capabilities to keep when executing the process inside the container // All capbilities not specified will be dropped from the processes capability mask diff --git a/config_test.go b/config_test.go index b4e16bf01..63b8aa8ad 100644 --- a/config_test.go +++ b/config_test.go @@ -64,12 +64,12 @@ func TestConfigJsonFormat(t *testing.T) { t.Fail() } - if getNamespaceIndex(container, "NEWNET") == -1 { + if container.Namespaces.index(NEWNET) == -1 { t.Log("namespaces should contain NEWNET") t.Fail() } - if getNamespaceIndex(container, "NEWUSER") != -1 { + if container.Namespaces.index(NEWUSER) != -1 { t.Log("namespaces should not contain NEWUSER") t.Fail() } @@ -158,12 +158,3 @@ func TestSelinuxLabels(t *testing.T) { t.Fatalf("expected mount label %q but received %q", label, container.MountConfig.MountLabel) } } - -func getNamespaceIndex(config *Config, name string) int { - for i, v := range config.Namespaces { - if v.Name == name { - return i - } - } - return -1 -} diff --git a/integration/exec_test.go b/integration/exec_test.go index cf749efbf..f0728c581 100644 --- a/integration/exec_test.go +++ b/integration/exec_test.go @@ -88,8 +88,7 @@ func TestIPCHost(t *testing.T) { } config := newTemplateConfig(rootfs) - i := getNamespaceIndex(config, "NEWIPC") - config.Namespaces = append(config.Namespaces[:i], config.Namespaces[i+1:]...) + config.Namespaces.Remove(libcontainer.NEWIPC) buffers, exitCode, err := runContainer(config, "", "readlink", "/proc/self/ns/ipc") if err != nil { t.Fatal(err) @@ -121,8 +120,7 @@ func TestIPCJoinPath(t *testing.T) { } config := newTemplateConfig(rootfs) - i := getNamespaceIndex(config, "NEWIPC") - config.Namespaces[i].Path = "/proc/1/ns/ipc" + config.Namespaces.Add(libcontainer.NEWIPC, "/proc/1/ns/ipc") buffers, exitCode, err := runContainer(config, "", "readlink", "/proc/self/ns/ipc") if err != nil { @@ -150,8 +148,7 @@ func TestIPCBadPath(t *testing.T) { defer remove(rootfs) config := newTemplateConfig(rootfs) - i := getNamespaceIndex(config, "NEWIPC") - config.Namespaces[i].Path = "/proc/1/ns/ipcc" + config.Namespaces.Add(libcontainer.NEWIPC, "/proc/1/ns/ipcc") _, _, err = runContainer(config, "", "true") if err == nil { @@ -179,12 +176,3 @@ func TestRlimit(t *testing.T) { t.Fatalf("expected rlimit to be 1024, got %s", limit) } } - -func getNamespaceIndex(config *libcontainer.Config, name string) int { - for i, v := range config.Namespaces { - if v.Name == name { - return i - } - } - return -1 -} diff --git a/integration/template_test.go b/integration/template_test.go index f37070ffb..7e56628c2 100644 --- a/integration/template_test.go +++ b/integration/template_test.go @@ -32,12 +32,12 @@ func newTemplateConfig(rootfs string) *libcontainer.Config { "KILL", "AUDIT_WRITE", }, - Namespaces: []libcontainer.Namespace{ - {Name: "NEWNS"}, - {Name: "NEWUTS"}, - {Name: "NEWIPC"}, - {Name: "NEWPID"}, - {Name: "NEWNET"}, + Namespaces: libcontainer.Namespaces{ + {Type: libcontainer.NEWNS}, + {Type: libcontainer.NEWUTS}, + {Type: libcontainer.NEWIPC}, + {Type: libcontainer.NEWPID}, + {Type: libcontainer.NEWNET}, }, Cgroups: &cgroups.Cgroup{ Parent: "integration", diff --git a/namespaces/init.go b/namespaces/init.go index 10e450214..a4400bddb 100644 --- a/namespaces/init.go +++ b/namespaces/init.go @@ -318,7 +318,7 @@ func joinExistingNamespaces(namespaces []libcontainer.Namespace) error { if err != nil { return err } - err = system.Setns(f.Fd(), uintptr(namespaceInfo[ns.Name])) + err = system.Setns(f.Fd(), uintptr(namespaceInfo[ns.Type])) f.Close() if err != nil { return err diff --git a/namespaces/utils.go b/namespaces/utils.go index 556ea6699..de71a379f 100644 --- a/namespaces/utils.go +++ b/namespaces/utils.go @@ -17,13 +17,13 @@ func (i initError) Error() string { return i.Message } -var namespaceInfo = map[string]int{ - "NEWNET": syscall.CLONE_NEWNET, - "NEWNS": syscall.CLONE_NEWNS, - "NEWUSER": syscall.CLONE_NEWUSER, - "NEWIPC": syscall.CLONE_NEWIPC, - "NEWUTS": syscall.CLONE_NEWUTS, - "NEWPID": syscall.CLONE_NEWPID, +var namespaceInfo = map[libcontainer.NamespaceType]int{ + libcontainer.NEWNET: syscall.CLONE_NEWNET, + libcontainer.NEWNS: syscall.CLONE_NEWNS, + libcontainer.NEWUSER: syscall.CLONE_NEWUSER, + libcontainer.NEWIPC: syscall.CLONE_NEWIPC, + libcontainer.NEWUTS: syscall.CLONE_NEWUTS, + libcontainer.NEWPID: syscall.CLONE_NEWPID, } // New returns a newly initialized Pipe for communication between processes @@ -37,9 +37,9 @@ func newInitPipe() (parent *os.File, child *os.File, err error) { // GetNamespaceFlags parses the container's Namespaces options to set the correct // flags on clone, unshare, and setns -func GetNamespaceFlags(namespaces []libcontainer.Namespace) (flag int) { +func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) { for _, v := range namespaces { - flag |= namespaceInfo[v.Name] + flag |= namespaceInfo[v.Type] } return flag } diff --git a/sample_configs/apparmor.json b/sample_configs/apparmor.json index 50421ec88..96f73cb79 100644 --- a/sample_configs/apparmor.json +++ b/sample_configs/apparmor.json @@ -177,11 +177,11 @@ ], "hostname": "koye", "namespaces": [ - {"name":"NEWIPC"}, - {"name": "NEWNET"}, - {"name": "NEWNS"}, - {"name": "NEWPID"}, - {"name": "NEWUTS"} + {"type":"NEWIPC"}, + {"type": "NEWNET"}, + {"type": "NEWNS"}, + {"type": "NEWPID"}, + {"type": "NEWUTS"} ], "networks": [ { diff --git a/sample_configs/attach_to_bridge.json b/sample_configs/attach_to_bridge.json index 9b190293a..e5c03a7ef 100644 --- a/sample_configs/attach_to_bridge.json +++ b/sample_configs/attach_to_bridge.json @@ -176,11 +176,11 @@ ], "hostname": "koye", "namespaces": [ - {"name": "NEWIPC"}, - {"name": "NEWNET"}, - {"name": "NEWNS"}, - {"name": "NEWPID"}, - {"name": "NEWUTS"} + {"type": "NEWIPC"}, + {"type": "NEWNET"}, + {"type": "NEWNS"}, + {"type": "NEWPID"}, + {"type": "NEWUTS"} ], "networks": [ { diff --git a/sample_configs/minimal.json b/sample_configs/minimal.json index 720be64f9..01de46746 100644 --- a/sample_configs/minimal.json +++ b/sample_configs/minimal.json @@ -182,11 +182,11 @@ ], "hostname": "koye", "namespaces": [ - {"name": "NEWIPC"}, - {"name": "NEWNET"}, - {"name": "NEWNS"}, - {"name": "NEWPID"}, - {"name": "NEWUTS"} + {"type": "NEWIPC"}, + {"type": "NEWNET"}, + {"type": "NEWNS"}, + {"type": "NEWPID"}, + {"type": "NEWUTS"} ], "networks": [ { diff --git a/sample_configs/route_source_address_selection.json b/sample_configs/route_source_address_selection.json index f403996dc..9c62045a4 100644 --- a/sample_configs/route_source_address_selection.json +++ b/sample_configs/route_source_address_selection.json @@ -176,11 +176,11 @@ ], "hostname": "koye", "namespaces": [ - {"name": "NEWIPC"}, - {"name": "NEWNET"}, - {"name": "NEWNS"}, - {"name": "NEWPID"}, - {"name": "NEWUTS"} + {"type": "NEWIPC"}, + {"type": "NEWNET"}, + {"type": "NEWNS"}, + {"type": "NEWPID"}, + {"type": "NEWUTS"} ], "networks": [ { diff --git a/sample_configs/selinux.json b/sample_configs/selinux.json index cfb83e09f..15556488a 100644 --- a/sample_configs/selinux.json +++ b/sample_configs/selinux.json @@ -178,11 +178,11 @@ ], "hostname": "koye", "namespaces": [ - {"name": "NEWIPC"}, - {"name": "NEWNET"}, - {"name": "NEWNS"}, - {"name": "NEWPID"}, - {"name": "NEWUTS"} + {"type": "NEWIPC"}, + {"type": "NEWNET"}, + {"type": "NEWNS"}, + {"type": "NEWPID"}, + {"type": "NEWUTS"} ], "networks": [ {