diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2019-07-26 15:06:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-26 15:06:06 +0200 |
commit | 0c4dfcfe57559d55786818b027ad12ad94574e71 (patch) | |
tree | f80b22ab5ccad6e896e4f96021891c81ec12b853 /pkg | |
parent | b212daa92f3a596efa87b6ccaa097f70cd34bb10 (diff) | |
parent | 1d72f651e4c5118c020a1ab7281d3de0bf31899e (diff) | |
download | podman-0c4dfcfe57559d55786818b027ad12ad94574e71.tar.gz podman-0c4dfcfe57559d55786818b027ad12ad94574e71.tar.bz2 podman-0c4dfcfe57559d55786818b027ad12ad94574e71.zip |
Merge pull request #3639 from giuseppe/user-ns-container
podman: support --userns=ns|container
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/pods.go | 22 | ||||
-rw-r--r-- | pkg/namespaces/namespaces.go | 29 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 24 | ||||
-rw-r--r-- | pkg/spec/spec.go | 4 |
4 files changed, 68 insertions, 11 deletions
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index 5960fac60..b9d7fcd9b 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -492,14 +492,28 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa if err != nil { return nil, err } + hasUserns := false + if podInfraID != "" { + podCtr, err := r.GetContainer(podInfraID) + if err != nil { + return nil, err + } + mappings, err := podCtr.IDMappings() + if err != nil { + return nil, err + } + hasUserns = len(mappings.UIDMap) > 0 + } namespaces := map[string]string{ // Disabled during code review per mheon //"pid": fmt.Sprintf("container:%s", podInfraID), - "net": fmt.Sprintf("container:%s", podInfraID), - "user": fmt.Sprintf("container:%s", podInfraID), - "ipc": fmt.Sprintf("container:%s", podInfraID), - "uts": fmt.Sprintf("container:%s", podInfraID), + "net": fmt.Sprintf("container:%s", podInfraID), + "ipc": fmt.Sprintf("container:%s", podInfraID), + "uts": fmt.Sprintf("container:%s", podInfraID), + } + if hasUserns { + namespaces["user"] = fmt.Sprintf("container:%s", podInfraID) } if !c.Quiet { writer = os.Stderr diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go index 7ed95bd0f..35298796f 100644 --- a/pkg/namespaces/namespaces.go +++ b/pkg/namespaces/namespaces.go @@ -76,27 +76,50 @@ func (n UsernsMode) IsKeepID() bool { // IsPrivate indicates whether the container uses the a private userns. func (n UsernsMode) IsPrivate() bool { - return !(n.IsHost()) + return !(n.IsHost() || n.IsContainer()) } // Valid indicates whether the userns is valid. func (n UsernsMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", "host", "keep-id": + case "", "host", "keep-id", "ns": + case "container": + if len(parts) != 2 || parts[1] == "" { + return false + } default: return false } return true } +// IsNS indicates a userns namespace passed in by path (ns:<path>) +func (n UsernsMode) IsNS() bool { + return strings.HasPrefix(string(n), "ns:") +} + +// NS gets the path associated with a ns:<path> userns ns +func (n UsernsMode) NS() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + // IsContainer indicates whether container uses a container userns. func (n UsernsMode) IsContainer() bool { - return false + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" } // Container is the id of the container which network this container is connected to. func (n UsernsMode) Container() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } return "" } diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 1fb1f829b..214a3c5ed 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -266,7 +266,8 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l } options = append(options, libpod.WithNetNSFrom(connectedCtr)) } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { - postConfigureNetNS := c.NetMode.IsSlirp4netns() || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() + hasUserns := c.UsernsMode.IsContainer() || c.UsernsMode.IsNS() || len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0 + postConfigureNetNS := c.NetMode.IsSlirp4netns() || (hasUserns && !c.UsernsMode.IsHost()) options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks)) } @@ -287,6 +288,26 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l options = append(options, libpod.WithCgroupNSFrom(connectedCtr)) } + if c.UsernsMode.IsNS() { + ns := c.UsernsMode.NS() + if ns == "" { + return nil, errors.Errorf("invalid empty user-defined user namespace") + } + _, err := os.Stat(ns) + if err != nil { + return nil, err + } + options = append(options, libpod.WithIDMappings(*c.IDMappings)) + } else if c.UsernsMode.IsContainer() { + connectedCtr, err := runtime.LookupContainer(c.UsernsMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.UsernsMode.Container()) + } + options = append(options, libpod.WithUserNSFrom(connectedCtr)) + } else { + options = append(options, libpod.WithIDMappings(*c.IDMappings)) + } + if c.PidMode.IsContainer() { connectedCtr, err := runtime.LookupContainer(c.PidMode.Container()) if err != nil { @@ -379,7 +400,6 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l } options = append(options, libpod.WithShmSize(c.Resources.ShmSize)) options = append(options, libpod.WithGroups(c.GroupAdd)) - options = append(options, libpod.WithIDMappings(*c.IDMappings)) if c.Rootfs != "" { options = append(options, libpod.WithRootFS(c.Rootfs)) } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 824c99025..15c8c77fa 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -46,7 +46,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM canMountSys := true isRootless := rootless.IsRootless() - inUserNS := isRootless || (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() + hasUserns := config.UsernsMode.IsContainer() || config.UsernsMode.IsNS() || len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0 + inUserNS := isRootless || (hasUserns && !config.UsernsMode.IsHost()) if inUserNS && config.NetMode.IsHost() { canMountSys = false @@ -554,7 +555,6 @@ func addUserNS(config *CreateConfig, g *generate.Generator) error { if err := g.AddOrReplaceLinuxNamespace(spec.UserNamespace, NS(string(config.UsernsMode))); err != nil { return err } - // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1)) g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1)) |