summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2020-12-01 16:23:40 -0500
committerUrvashi Mohnani <umohnani@redhat.com>2021-08-09 15:17:22 -0400
commit221b1add74e17ded10e8f2f832a53065578aa264 (patch)
tree499c89b26092c92026f3e7532b6bd633d920652f /libpod
parent431707c72044154b956944d00b1ba40b303decb2 (diff)
downloadpodman-221b1add74e17ded10e8f2f832a53065578aa264.tar.gz
podman-221b1add74e17ded10e8f2f832a53065578aa264.tar.bz2
podman-221b1add74e17ded10e8f2f832a53065578aa264.zip
Add support for pod inside of user namespace.
Add the --userns flag to podman pod create and keep track of the userns setting that pod was created with so that all containers created within the pod will inherit that userns setting. Specifically we need to be able to launch a pod with --userns=keep-id Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go4
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/container_internal_linux.go4
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/options.go24
-rw-r--r--libpod/pod.go1
-rw-r--r--libpod/pod_api.go1
-rw-r--r--libpod/runtime_pod_infra_linux.go37
8 files changed, 68 insertions, 11 deletions
diff --git a/libpod/container.go b/libpod/container.go
index f3f4b27b7..d5d5ef1a5 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -1020,8 +1020,8 @@ func (c *Container) RWSize() (int64, error) {
}
// IDMappings returns the UID/GID mapping used for the container
-func (c *Container) IDMappings() (storage.IDMappingOptions, error) {
- return c.config.IDMappings, nil
+func (c *Container) IDMappings() storage.IDMappingOptions {
+ return c.config.IDMappings
}
// RootUID returns the root user mapping from container
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 8ffcccf4c..3f7a4807d 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -367,6 +367,12 @@ func (c *Container) setupStorageMapping(dest, from *storage.IDMappingOptions) {
return
}
*dest = *from
+ // If we are creating a container inside a pod, we always want to inherit the
+ // userns settings from the infra container. So clear the auto userns settings
+ // so that we don't request storage for a new uid/gid map.
+ if c.PodID() != "" && !c.IsInfra() {
+ dest.AutoUserNs = false
+ }
if dest.AutoUserNs {
overrides := c.getUserOverrides()
dest.AutoUserNsOpts.PasswdFile = overrides.ContainerEtcPasswdPath
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index f30f622ac..6d2f7bddc 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -659,7 +659,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
- if c.config.IDMappings.AutoUserNs {
+ if c.config.UserNsCtr == "" && c.config.IDMappings.AutoUserNs {
if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
return nil, err
}
@@ -1884,7 +1884,7 @@ func (c *Container) generateResolvConf() (string, error) {
return "", err
}
- return filepath.Join(c.state.RunDir, "resolv.conf"), nil
+ return destPath, nil
}
// generateHosts creates a containers hosts file
diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go
index a17304875..f91fd198d 100644
--- a/libpod/define/pod_inspect.go
+++ b/libpod/define/pod_inspect.go
@@ -105,6 +105,8 @@ type InspectPodInfraConfig struct {
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
// Pid is the PID namespace mode of the pod's infra container
PidNS string `json:"pid_ns,omitempty"`
+ // UserNS is the usernamespace that all the containers in the pod will join.
+ UserNS string `json:"userns,omitempty"`
}
// InspectPodContainerInfo contains information on a container in a pod.
diff --git a/libpod/options.go b/libpod/options.go
index 071b085e7..b94ef88ba 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -956,8 +956,9 @@ func WithUserNSFrom(nsCtr *Container) CtrCreateOption {
}
ctr.config.UserNsCtr = nsCtr.ID()
- ctr.config.IDMappings = nsCtr.config.IDMappings
-
+ if err := JSONDeepCopy(nsCtr.IDMappings(), &ctr.config.IDMappings); err != nil {
+ return err
+ }
g := generate.Generator{Config: ctr.config.Spec}
g.ClearLinuxUIDMappings()
@@ -968,7 +969,6 @@ func WithUserNSFrom(nsCtr *Container) CtrCreateOption {
for _, gidmap := range nsCtr.config.IDMappings.GIDMap {
g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
}
- ctr.config.IDMappings = nsCtr.config.IDMappings
return nil
}
}
@@ -2423,6 +2423,24 @@ func WithVolatile() CtrCreateOption {
}
ctr.config.Volatile = true
+
+ return nil
+ }
+}
+
+// WithPodUserns sets the userns for the infra container in a pod.
+func WithPodUserns(userns specgen.Namespace) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod userns as no infra container is being created")
+ }
+
+ pod.config.InfraContainer.Userns = userns
+
return nil
}
}
diff --git a/libpod/pod.go b/libpod/pod.go
index 0fef7f6f3..7df15df7b 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -117,6 +117,7 @@ type InfraContainerConfig struct {
Slirp4netns bool `json:"slirp4netns,omitempty"`
NetworkOptions map[string][]string `json:"network_options,omitempty"`
ResourceLimits *specs.LinuxResources `json:"resource_limits,omitempty"`
+ Userns specgen.Namespace `json:"userns,omitempty"`
}
// ID retrieves the pod's ID
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 90d67dbb0..6fea2dfd8 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -593,6 +593,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
infraConfig.CPUQuota = p.CPUQuota()
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
infraConfig.PidNS = p.PidMode()
+ infraConfig.UserNS = p.config.InfraContainer.Userns.String()
if len(p.config.InfraContainer.DNSServer) > 0 {
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index d4f861118..49213032e 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -8,7 +8,9 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/util"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -110,9 +112,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
options = append(options, WithNetworkOptions(p.config.InfraContainer.NetworkOptions))
}
}
- // PostConfigureNetNS should not be set since user namespace sharing is not implemented
- // and rootless networking no longer supports post configuration setup
- options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks))
+ options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, !p.config.InfraContainer.Userns.IsHost(), netmode, p.config.InfraContainer.Networks))
}
// For each option in InfraContainerConfig - if set, pass into
@@ -158,11 +158,39 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
g.Config.Linux.Namespaces = newNS
}
}
+
+ for _, ctl := range r.config.Containers.DefaultSysctls {
+ sysctl := strings.SplitN(ctl, "=", 2)
+ if len(sysctl) < 2 {
+ return nil, errors.Errorf("invalid default sysctl %s", ctl)
+ }
+
+ // Ignore net sysctls if --net=host
+ if p.config.InfraContainer.HostNetwork && strings.HasPrefix(sysctl[0], "net.") {
+ logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace set to host", sysctl[0], sysctl[1])
+ continue
+ }
+
+ g.AddLinuxSysctl(sysctl[0], sysctl[1])
+ }
+
g.SetRootReadonly(true)
g.SetProcessArgs(infraCtrCommand)
logrus.Debugf("Using %q as infra container command", infraCtrCommand)
+ mapopt, err := util.ParseIDMapping(namespaces.UsernsMode(p.config.InfraContainer.Userns.String()), []string{}, []string{}, "", "")
+ if err != nil {
+ return nil, err
+ }
+ user, err := specgen.SetupUserNS(mapopt, p.config.InfraContainer.Userns, &g)
+ if err != nil {
+ return nil, err
+ }
+ if user != "" {
+ options = append(options, WithUser(user))
+ }
+
g.RemoveMount("/dev/shm")
if isRootless {
g.RemoveMount("/dev/pts")
@@ -210,14 +238,15 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName))
options = append(options, WithName(containerName))
options = append(options, withIsInfra())
+ options = append(options, WithIDMappings(*mapopt))
if len(p.config.InfraContainer.ConmonPidFile) > 0 {
options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile))
}
newRes := new(spec.LinuxResources)
newRes.CPU = new(spec.LinuxCPU)
newRes.CPU = p.ResourceLim().CPU
-
g.Config.Linux.Resources.CPU = newRes.CPU
+
return r.newContainer(ctx, g.Config, options...)
}