diff options
author | Doug Rabson <dfr@rabson.org> | 2022-08-27 13:15:05 +0100 |
---|---|---|
committer | Doug Rabson <dfr@rabson.org> | 2022-09-05 10:17:49 +0100 |
commit | c1a86a8c4cbd8be87dbf11277aee055b89c8519a (patch) | |
tree | de893136d0757ff6a6a581a66a8b51b37af45b2e /libpod | |
parent | e101f4350bdbaad6a70669977a0a254b1bfcb1d3 (diff) | |
download | podman-c1a86a8c4cbd8be87dbf11277aee055b89c8519a.tar.gz podman-c1a86a8c4cbd8be87dbf11277aee055b89c8519a.tar.bz2 podman-c1a86a8c4cbd8be87dbf11277aee055b89c8519a.zip |
libpod: Factor out platform-specific sections from generateSpec
[NO NEW TESTS NEEDED]
Signed-off-by: Doug Rabson <dfr@rabson.org>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_common.go | 156 | ||||
-rw-r--r-- | libpod/container_internal_freebsd.go | 82 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 178 |
3 files changed, 266 insertions, 150 deletions
diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index 50d7375cd..95d3c8ad8 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -89,16 +89,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } // If network namespace was requested, add it now - if c.config.CreateNetNS { - if c.config.PostConfigureNetNS { - if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), ""); err != nil { - return nil, err - } - } else { - if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), c.state.NetNS.Path()); err != nil { - return nil, err - } - } + if err := c.addNetworkNamespace(&g); err != nil { + return nil, err } // Apply AppArmor checks and load the default profile if needed. @@ -222,8 +214,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { m.Options = options } - g.SetProcessSelinuxLabel(c.ProcessLabel()) - g.SetLinuxMountLabel(c.MountLabel()) + c.setProcessLabel(&g) + c.setMountLabel(&g) // Add bind mounts to container for dstPath, srcPath := range c.state.BindMounts { @@ -351,10 +343,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } - if c.Systemd() { - if err := c.setupSystemd(g.Mounts(), g); err != nil { - return nil, fmt.Errorf("error adding systemd-specific mounts: %w", err) - } + if err := c.addSystemdMounts(&g); err != nil { + return nil, err } // Look up and add groups the user belongs to, if a group wasn't directly specified @@ -400,106 +390,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } // Add shared namespaces from other containers - if c.config.IPCNsCtr != "" { - if err := c.addNamespaceContainer(&g, IPCNS, c.config.IPCNsCtr, spec.IPCNamespace); err != nil { - return nil, err - } - } - if c.config.MountNsCtr != "" { - if err := c.addNamespaceContainer(&g, MountNS, c.config.MountNsCtr, spec.MountNamespace); err != nil { - return nil, err - } - } - if c.config.NetNsCtr != "" { - if err := c.addNamespaceContainer(&g, NetNS, c.config.NetNsCtr, spec.NetworkNamespace); err != nil { - return nil, err - } - } - if c.config.PIDNsCtr != "" { - if err := c.addNamespaceContainer(&g, PIDNS, c.config.PIDNsCtr, spec.PIDNamespace); err != nil { - return nil, err - } - } - if c.config.UserNsCtr != "" { - if err := c.addNamespaceContainer(&g, UserNS, c.config.UserNsCtr, spec.UserNamespace); err != nil { - return nil, err - } - if len(g.Config.Linux.UIDMappings) == 0 { - // 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)) - } - } - - availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps() - if err != nil { - if os.IsNotExist(err) { - // The kernel-provided files only exist if user namespaces are supported - logrus.Debugf("User or group ID mappings not available: %s", err) - } else { - return nil, err - } - } else { - g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs) - g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs) - } - - // Hostname handling: - // If we have a UTS namespace, set Hostname in the OCI spec. - // Set the HOSTNAME environment variable unless explicitly overridden by - // the user (already present in OCI spec). If we don't have a UTS ns, - // set it to the host's hostname instead. - hostname := c.Hostname() - foundUTS := false - - for _, i := range c.config.Spec.Linux.Namespaces { - if i.Type == spec.UTSNamespace && i.Path == "" { - foundUTS = true - g.SetHostname(hostname) - break - } - } - if !foundUTS { - tmpHostname, err := os.Hostname() - if err != nil { - return nil, err - } - hostname = tmpHostname - } - needEnv := true - for _, checkEnv := range g.Config.Process.Env { - if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" { - needEnv = false - break - } - } - if needEnv { - g.AddProcessEnv("HOSTNAME", hostname) - } - - if c.config.UTSNsCtr != "" { - if err := c.addNamespaceContainer(&g, UTSNS, c.config.UTSNsCtr, spec.UTSNamespace); err != nil { - return nil, err - } - } - if c.config.CgroupNsCtr != "" { - if err := c.addNamespaceContainer(&g, CgroupNS, c.config.CgroupNsCtr, spec.CgroupNamespace); err != nil { - return nil, err - } - } - - if c.config.UserNsCtr == "" && c.config.IDMappings.AutoUserNs { - if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil { - return nil, err - } - g.ClearLinuxUIDMappings() - for _, uidmap := range c.config.IDMappings.UIDMap { - g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size)) - } - g.ClearLinuxGIDMappings() - for _, gidmap := range c.config.IDMappings.GIDMap { - g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size)) - } + if err := c.addSharedNamespaces(&g); err != nil { + return nil, err } g.SetRootPath(c.state.Mountpoint) @@ -510,13 +402,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { g.AddAnnotation(annotations.ContainerManager, annotations.ContainerManagerLibpod) } - cgroupPath, err := c.getOCICgroupPath() - if err != nil { + if err := c.setCgroupsPath(&g); err != nil { return nil, err } - g.SetLinuxCgroupsPath(cgroupPath) - // Warning: CDI may alter g.Config in place. if len(c.config.CDIDevices) > 0 { registry := cdi.GetRegistry( @@ -535,14 +424,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { mounts := sortMounts(g.Mounts()) g.ClearMounts() - // Determine property of RootPropagation based on volume properties. If - // a volume is shared, then keep root propagation shared. This should - // work for slave and private volumes too. - // - // For slave volumes, it can be either [r]shared/[r]slave. - // - // For private volumes any root propagation value should work. - rootPropagation := "" for _, m := range mounts { // We need to remove all symlinks from tmpfs mounts. // Runc and other runtimes may choke on them. @@ -557,25 +438,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { m.Destination = trimmedPath } g.AddMount(m) - for _, opt := range m.Options { - switch opt { - case MountShared, MountRShared: - if rootPropagation != MountShared && rootPropagation != MountRShared { - rootPropagation = MountShared - } - case MountSlave, MountRSlave: - if rootPropagation != MountShared && rootPropagation != MountRShared && rootPropagation != MountSlave && rootPropagation != MountRSlave { - rootPropagation = MountRSlave - } - } - } } - if rootPropagation != "" { - logrus.Debugf("Set root propagation to %q", rootPropagation) - if err := g.SetLinuxRootPropagation(rootPropagation); err != nil { - return nil, err - } + if err := c.addRootPropagation(&g, mounts); err != nil { + return nil, err } // Warning: precreate hooks may alter g.Config in place. diff --git a/libpod/container_internal_freebsd.go b/libpod/container_internal_freebsd.go index 9cfef5c70..65a74a2e4 100644 --- a/libpod/container_internal_freebsd.go +++ b/libpod/container_internal_freebsd.go @@ -9,7 +9,6 @@ import ( "fmt" "io" "io/ioutil" - "math" "os" "os/user" "path" @@ -22,10 +21,8 @@ import ( metadata "github.com/checkpoint-restore/checkpointctl/lib" "github.com/checkpoint-restore/go-criu/v5/stats" - cdi "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" "github.com/containers/buildah/pkg/chrootuser" "github.com/containers/buildah/pkg/overlay" - butil "github.com/containers/buildah/util" "github.com/containers/common/libnetwork/etchosts" "github.com/containers/common/libnetwork/resolvconf" "github.com/containers/common/libnetwork/types" @@ -33,10 +30,8 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/subscriptions" "github.com/containers/common/pkg/umask" - cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" - "github.com/containers/podman/v4/pkg/annotations" "github.com/containers/podman/v4/pkg/checkpoint/crutils" "github.com/containers/podman/v4/pkg/criu" "github.com/containers/podman/v4/pkg/lookup" @@ -2129,3 +2124,80 @@ func openDirectory(path string) (fd int, err error) { const O_PATH = 0x00400000 return unix.Open(path, unix.O_RDONLY|O_PATH, 0) } + +func (c *Container) addNetworkNamespace(g *generate.Generator) error { + if c.config.CreateNetNS { + g.AddAnnotation("org.freebsd.parentJail", c.state.NetworkJail) + } + return nil +} + +func (c *Container) addSystemdMounts(g *generate.Generator) error { + return nil +} + +func (c *Container) addSharedNamespaces(g *generate.Generator) error { + if c.config.NetNsCtr != "" { + if err := c.addNetworkContainer(g, c.config.NetNsCtr); err != nil { + return err + } + } + + availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps() + if err != nil { + if os.IsNotExist(err) { + // The kernel-provided files only exist if user namespaces are supported + logrus.Debugf("User or group ID mappings not available: %s", err) + } else { + return err + } + } else { + g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs) + g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs) + } + + // Hostname handling: + // If we have a UTS namespace, set Hostname in the OCI spec. + // Set the HOSTNAME environment variable unless explicitly overridden by + // the user (already present in OCI spec). If we don't have a UTS ns, + // set it to the host's hostname instead. + hostname := c.Hostname() + foundUTS := false + + // TODO: make this optional, needs progress on adding FreeBSD section to the spec + foundUTS = true + g.SetHostname(hostname) + + if !foundUTS { + tmpHostname, err := os.Hostname() + if err != nil { + return err + } + hostname = tmpHostname + } + needEnv := true + for _, checkEnv := range g.Config.Process.Env { + if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" { + needEnv = false + break + } + } + if needEnv { + g.AddProcessEnv("HOSTNAME", hostname) + } + return nil +} + +func (c *Container) addRootPropagation(g *generate.Generator, mounts []spec.Mount) error { + return nil +} + +func (c *Container) setProcessLabel(g *generate.Generator) { +} + +func (c *Container) setMountLabel(g *generate.Generator) { +} + +func (c *Container) setCgroupsPath(g *generate.Generator) error { + return nil +} diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 5ec9d8e43..1cec3a7bc 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -2666,3 +2666,181 @@ func (c *Container) setupRootlessNetwork() error { func openDirectory(path string) (fd int, err error) { return unix.Open(path, unix.O_RDONLY|unix.O_PATH, 0) } + +func (c *Container) addNetworkNamespace(g *generate.Generator) error { + if c.config.CreateNetNS { + if c.config.PostConfigureNetNS { + if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), ""); err != nil { + return err + } + } else { + if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), c.state.NetNS.Path()); err != nil { + return err + } + } + } + return nil +} + +func (c *Container) addSystemdMounts(g *generate.Generator) error { + if c.Systemd() { + if err := c.setupSystemd(g.Mounts(), *g); err != nil { + return fmt.Errorf("error adding systemd-specific mounts: %w", err) + } + } + return nil +} + +func (c *Container) addSharedNamespaces(g *generate.Generator) error { + if c.config.IPCNsCtr != "" { + if err := c.addNamespaceContainer(g, IPCNS, c.config.IPCNsCtr, spec.IPCNamespace); err != nil { + return err + } + } + if c.config.MountNsCtr != "" { + if err := c.addNamespaceContainer(g, MountNS, c.config.MountNsCtr, spec.MountNamespace); err != nil { + return err + } + } + if c.config.NetNsCtr != "" { + if err := c.addNamespaceContainer(g, NetNS, c.config.NetNsCtr, spec.NetworkNamespace); err != nil { + return err + } + } + if c.config.PIDNsCtr != "" { + if err := c.addNamespaceContainer(g, PIDNS, c.config.PIDNsCtr, spec.PIDNamespace); err != nil { + return err + } + } + if c.config.UserNsCtr != "" { + if err := c.addNamespaceContainer(g, UserNS, c.config.UserNsCtr, spec.UserNamespace); err != nil { + return err + } + if len(g.Config.Linux.UIDMappings) == 0 { + // 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)) + } + } + + availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps() + if err != nil { + if os.IsNotExist(err) { + // The kernel-provided files only exist if user namespaces are supported + logrus.Debugf("User or group ID mappings not available: %s", err) + } else { + return err + } + } else { + g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs) + g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs) + } + + // Hostname handling: + // If we have a UTS namespace, set Hostname in the OCI spec. + // Set the HOSTNAME environment variable unless explicitly overridden by + // the user (already present in OCI spec). If we don't have a UTS ns, + // set it to the host's hostname instead. + hostname := c.Hostname() + foundUTS := false + + for _, i := range c.config.Spec.Linux.Namespaces { + if i.Type == spec.UTSNamespace && i.Path == "" { + foundUTS = true + g.SetHostname(hostname) + break + } + } + if !foundUTS { + tmpHostname, err := os.Hostname() + if err != nil { + return err + } + hostname = tmpHostname + } + needEnv := true + for _, checkEnv := range g.Config.Process.Env { + if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" { + needEnv = false + break + } + } + if needEnv { + g.AddProcessEnv("HOSTNAME", hostname) + } + + if c.config.UTSNsCtr != "" { + if err := c.addNamespaceContainer(g, UTSNS, c.config.UTSNsCtr, spec.UTSNamespace); err != nil { + return err + } + } + if c.config.CgroupNsCtr != "" { + if err := c.addNamespaceContainer(g, CgroupNS, c.config.CgroupNsCtr, spec.CgroupNamespace); err != nil { + return err + } + } + + if c.config.UserNsCtr == "" && c.config.IDMappings.AutoUserNs { + if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil { + return err + } + g.ClearLinuxUIDMappings() + for _, uidmap := range c.config.IDMappings.UIDMap { + g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size)) + } + g.ClearLinuxGIDMappings() + for _, gidmap := range c.config.IDMappings.GIDMap { + g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size)) + } + } + return nil +} + +func (c *Container) addRootPropagation(g *generate.Generator, mounts []spec.Mount) error { + // Determine property of RootPropagation based on volume properties. If + // a volume is shared, then keep root propagation shared. This should + // work for slave and private volumes too. + // + // For slave volumes, it can be either [r]shared/[r]slave. + // + // For private volumes any root propagation value should work. + rootPropagation := "" + for _, m := range mounts { + for _, opt := range m.Options { + switch opt { + case MountShared, MountRShared: + if rootPropagation != MountShared && rootPropagation != MountRShared { + rootPropagation = MountShared + } + case MountSlave, MountRSlave: + if rootPropagation != MountShared && rootPropagation != MountRShared && rootPropagation != MountSlave && rootPropagation != MountRSlave { + rootPropagation = MountRSlave + } + } + } + } + if rootPropagation != "" { + logrus.Debugf("Set root propagation to %q", rootPropagation) + if err := g.SetLinuxRootPropagation(rootPropagation); err != nil { + return err + } + } + return nil +} + +func (c *Container) setProcessLabel(g *generate.Generator) { + g.SetProcessSelinuxLabel(c.ProcessLabel()) +} + +func (c *Container) setMountLabel(g *generate.Generator) { + g.SetLinuxMountLabel(c.MountLabel()) +} + +func (c *Container) setCgroupsPath(g *generate.Generator) error { + cgroupPath, err := c.getOCICgroupPath() + if err != nil { + return err + } + g.SetLinuxCgroupsPath(cgroupPath) + return nil +} |