diff --git a/generate.go b/generate.go index 3b6c740ad..363718763 100644 --- a/generate.go +++ b/generate.go @@ -31,6 +31,7 @@ var generateFlags = []cli.Flag{ cli.StringFlag{Name: "mount", Usage: "mount namespace"}, cli.StringFlag{Name: "pid", Usage: "pid namespace"}, cli.StringFlag{Name: "ipc", Usage: "ipc namespace"}, + cli.StringFlag{Name: "user", Usage: "user namespace"}, cli.StringFlag{Name: "uts", Usage: "uts namespace"}, cli.StringFlag{Name: "selinux-label", Usage: "process selinux label"}, cli.StringFlag{Name: "mount-label", Usage: "selinux mount context label"}, @@ -463,10 +464,6 @@ func addIDMappings(spec *rspec.Spec, context *cli.Context) error { } } - if len(context.StringSlice("uidmappings")) > 0 || len(context.StringSlice("gidmappings")) > 0 { - spec.Linux.Namespaces = append(spec.Linux.Namespaces, rspec.Namespace{Type: "user"}) - } - return nil } @@ -660,17 +657,45 @@ func mapStrToNamespace(ns string, path string) rspec.Namespace { } func setupNamespaces(spec *rspec.Spec, context *cli.Context) { - namespaces := []string{"network", "pid", "mount", "ipc", "uts"} - var linuxNs []rspec.Namespace + var needsNewUser = false + if len(context.StringSlice("uidmappings")) > 0 || len(context.StringSlice("gidmappings")) > 0 { + needsNewUser = true + } + + namespaces := []string{"network", "pid", "mount", "ipc", "uts", "user"} for _, nsName := range namespaces { + if !context.IsSet(nsName) && !(needsNewUser && nsName == "user") { + continue + } nsPath := context.String(nsName) if nsPath == "host" { + ns := mapStrToNamespace(nsName, "") + removeNamespace(&spec.Linux.Namespaces, ns.Type) continue } ns := mapStrToNamespace(nsName, nsPath) - linuxNs = append(linuxNs, ns) + replaceOrAppendNamespace(&spec.Linux.Namespaces, ns) + } +} + +func replaceOrAppendNamespace(namespaces *[]rspec.Namespace, namespace rspec.Namespace) { + for i, ns := range *namespaces { + if ns.Type == namespace.Type { + (*namespaces)[i] = namespace + return + } + } + new := append(*namespaces, namespace) + *namespaces = new +} + +func removeNamespace(namespaces *[]rspec.Namespace, namespaceType rspec.NamespaceType) { + for i, ns := range *namespaces { + if ns.Type == namespaceType { + *namespaces = append((*namespaces)[:i], (*namespaces)[i+1:]...) + return + } } - spec.Linux.Namespaces = linuxNs } func sPtr(s string) *string { return &s } diff --git a/man/ocitools-generate.1.md b/man/ocitools-generate.1.md index 335774285..cd2bbf169 100644 --- a/man/ocitools-generate.1.md +++ b/man/ocitools-generate.1.md @@ -57,7 +57,7 @@ inside of the container. Gid for the process inside of container **--gidmappings**=GIDMAPPINGS - Add GIDMappings e.g HostID:ContainerID:Size for use with User Namespace + Add GIDMappings e.g HostID:ContainerID:Size. Implies **-user=**. **--groups**=GROUP Supplementary groups for the processes inside of container @@ -70,11 +70,15 @@ inside of the container. Sets the container host name that is available inside the container. -**--ipc** - Use ipc namespace +**--ipc**=[*PATH*] + Use an IPC namespace. If *PATH* is set, join that namespace. If it + is unset, create a new namespace. The special *PATH* `host` removes + any existing IPC namespace from the configuration. -**--mount** - Use a mount namespace +**--mount**=[*PATH*] + Use a network namespace. If *PATH* is set, join that namespace. If + it is unset, create a new namespace. The special *PATH* `host` + removes any existing mount namespace from the configuration. **--mount-cgroups**=[rw|ro|no] Mount cgroups. The default is `no`. @@ -91,8 +95,10 @@ inside of the container. "system_u:object_r:usr_t:s0" might be a good label for a readonly container, "system_u:system_r:svirt_sandbox_file_t:s0:c1,c2" for a read/write container. -**--network** - Use network namespace +**--network**=[*PATH*] + Use a network namespace. If *PATH* is set, join that namespace. If + it is unset, create a new namespace. The special *PATH* `host` + removes any existing network namespace from the configuration. **--no-new-privileges** Set no new privileges bit for the container process. Setting this flag @@ -103,8 +109,10 @@ inside of the container. **--os**=OS Operating system used within the container -**--pid** - Use a pid namespace +**--pid**=[*PATH*] + Use a PID namespace. If *PATH* is set, join that namespace. If it + is unset, create a new namespace. The special *PATH* `host` removes + any existing UTS namespace from the configuration. **--poststart**=CMD Path to command to run in poststart hooks. This command will be run before @@ -183,10 +191,17 @@ inside of the container. Sets the UID used within the container. **--uidmappings** - Add UIDMappings e.g HostUID:ContainerID:Size for use with User Namespace + Add UIDMappings e.g HostUID:ContainerID:Size. Implies **--user=**. -**--uts** - Use the uts namespace +**--user**=[*PATH*] + Use a user namespace. If *PATH* is set, join that namespace. If it + is unset, create a new namespace. The special *PATH* `host` removes + any existing user namespace from the configuration. + +**--uts**=[*PATH*] + Use a UTS namespace. If *PATH* is set, join that namespace. If it + is unset, create a new namespace. The special *PATH* `host` removes + any existing UTS namespace from the configuration. # EXAMPLES