summaryrefslogtreecommitdiff
path: root/pkg/spec/spec.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/spec/spec.go')
-rw-r--r--pkg/spec/spec.go315
1 files changed, 27 insertions, 288 deletions
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 33e9ec076..7a220012f 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -1,7 +1,6 @@
package createconfig
import (
- "os"
"strings"
"github.com/containers/libpod/libpod"
@@ -10,13 +9,11 @@ import (
"github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/sysinfo"
- "github.com/docker/docker/oci/caps"
"github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
const cpuPeriod = 100000
@@ -47,14 +44,13 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
canMountSys := true
isRootless := rootless.IsRootless()
- hasUserns := config.UsernsMode.IsContainer() || config.UsernsMode.IsNS() || len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0
- inUserNS := isRootless || (hasUserns && !config.UsernsMode.IsHost())
+ inUserNS := config.User.InNS(isRootless)
- if inUserNS && config.NetMode.IsHost() {
+ if inUserNS && config.Network.NetMode.IsHost() {
canMountSys = false
}
- if config.Privileged && canMountSys {
+ if config.Security.Privileged && canMountSys {
cgroupPerm = "rw"
g.RemoveMount("/sys")
sysMnt := spec.Mount{
@@ -68,7 +64,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
addCgroup = false
g.RemoveMount("/sys")
r := "ro"
- if config.Privileged {
+ if config.Security.Privileged {
r = "rw"
}
sysMnt := spec.Mount{
@@ -78,7 +74,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"},
}
g.AddMount(sysMnt)
- if !config.Privileged && isRootless {
+ if !config.Security.Privileged && isRootless {
g.AddLinuxMaskedPaths("/sys/kernel")
}
}
@@ -92,9 +88,9 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
// When using a different user namespace, check that the GID 5 is mapped inside
// the container.
- if gid5Available && len(config.IDMappings.GIDMap) > 0 {
+ if gid5Available && len(config.User.IDMappings.GIDMap) > 0 {
mappingFound := false
- for _, r := range config.IDMappings.GIDMap {
+ for _, r := range config.User.IDMappings.GIDMap {
if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size {
mappingFound = true
break
@@ -117,7 +113,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
g.AddMount(devPts)
}
- if inUserNS && config.IpcMode.IsHost() {
+ if inUserNS && config.Ipc.IpcMode.IsHost() {
g.RemoveMount("/dev/mqueue")
devMqueue := spec.Mount{
Destination: "/dev/mqueue",
@@ -127,7 +123,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
g.AddMount(devMqueue)
}
- if inUserNS && config.PidMode.IsHost() {
+ if inUserNS && config.Pid.PidMode.IsHost() {
g.RemoveMount("/proc")
procMount := spec.Mount{
Destination: "/proc",
@@ -154,55 +150,6 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
for key, val := range config.Annotations {
g.AddAnnotation(key, val)
}
- g.SetRootReadonly(config.ReadOnlyRootfs)
-
- if config.HTTPProxy {
- for _, envSpec := range []string{
- "http_proxy",
- "HTTP_PROXY",
- "https_proxy",
- "HTTPS_PROXY",
- "ftp_proxy",
- "FTP_PROXY",
- "no_proxy",
- "NO_PROXY",
- } {
- envVal := os.Getenv(envSpec)
- if envVal != "" {
- g.AddProcessEnv(envSpec, envVal)
- }
- }
- }
-
- hostname := config.Hostname
- if hostname == "" {
- if utsCtrID := config.UtsMode.Container(); utsCtrID != "" {
- utsCtr, err := runtime.GetContainer(utsCtrID)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", utsCtrID)
- }
- hostname = utsCtr.Hostname()
- } else if config.NetMode.IsHost() || config.UtsMode.IsHost() {
- hostname, err = os.Hostname()
- if err != nil {
- return nil, errors.Wrap(err, "unable to retrieve hostname of the host")
- }
- } else {
- logrus.Debug("No hostname set; container's hostname will default to runtime default")
- }
- }
- g.RemoveHostname()
- if config.Hostname != "" || !config.UtsMode.IsHost() {
- // Set the hostname in the OCI configuration only
- // if specified by the user or if we are creating
- // a new UTS namespace.
- g.SetHostname(hostname)
- }
- g.AddProcessEnv("HOSTNAME", hostname)
-
- for sysctlKey, sysctlVal := range config.Sysctl {
- g.AddLinuxSysctl(sysctlKey, sysctlVal)
- }
g.AddProcessEnv("container", "podman")
addedResources := false
@@ -272,7 +219,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
// Devices
- if config.Privileged {
+ if config.Security.Privileged {
// If privileged, we need to add all the host devices to the
// spec. We do not add the user provided ones because we are
// already adding them all.
@@ -287,17 +234,11 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
}
- for _, uidmap := range config.IDMappings.UIDMap {
- g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
- }
- for _, gidmap := range config.IDMappings.GIDMap {
- g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
- }
// SECURITY OPTS
- g.SetProcessNoNewPrivileges(config.NoNewPrivs)
+ g.SetProcessNoNewPrivileges(config.Security.NoNewPrivs)
- if !config.Privileged {
- g.SetProcessApparmorProfile(config.ApparmorProfile)
+ if !config.Security.Privileged {
+ g.SetProcessApparmorProfile(config.Security.ApparmorProfile)
}
blockAccessToKernelFilesystems(config, &g)
@@ -341,54 +282,35 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
return nil, err
}
- if err := addPidNS(config, &g); err != nil {
+ // NAMESPACES
+
+ if err := config.Pid.ConfigureGenerator(&g); err != nil {
return nil, err
}
- if err := addUserNS(config, &g); err != nil {
+ if err := config.User.ConfigureGenerator(&g); err != nil {
return nil, err
}
- if err := addNetNS(config, &g); err != nil {
+ if err := config.Network.ConfigureGenerator(&g); err != nil {
return nil, err
}
- if err := addUTSNS(config, &g); err != nil {
+ if err := config.Uts.ConfigureGenerator(&g, &config.Network, runtime); err != nil {
return nil, err
}
- if err := addIpcNS(config, &g); err != nil {
+ if err := config.Ipc.ConfigureGenerator(&g); err != nil {
return nil, err
}
- if err := addCgroupNS(config, &g); err != nil {
+ if err := config.Cgroup.ConfigureGenerator(&g); err != nil {
return nil, err
}
configSpec := g.Config
- // HANDLE CAPABILITIES
- // NOTE: Must happen before SECCOMP
- if !config.Privileged {
- if err := setupCapabilities(config, configSpec); err != nil {
- return nil, err
- }
- } else {
- g.SetupPrivileged(true)
- }
-
- // HANDLE SECCOMP
-
- if config.SeccompProfilePath != "unconfined" {
- seccompConfig, err := getSeccompConfig(config, configSpec)
- if err != nil {
- return nil, err
- }
- configSpec.Linux.Seccomp = seccompConfig
- }
-
- // Clear default Seccomp profile from Generator for privileged containers
- if config.SeccompProfilePath == "unconfined" || config.Privileged {
- configSpec.Linux.Seccomp = nil
+ if err := config.Security.ConfigureGenerator(&g, &config.User); err != nil {
+ return nil, err
}
// BIND MOUNTS
@@ -430,7 +352,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
}
- switch config.Cgroups {
+ switch config.Cgroup.Cgroups {
case "disabled":
if addedResources {
return nil, errors.New("cannot specify resource limits when cgroups are disabled is specified")
@@ -461,48 +383,23 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
configSpec.Annotations[libpod.InspectAnnotationVolumesFrom] = strings.Join(config.VolumesFrom, ",")
}
- if config.Privileged {
+ if config.Security.Privileged {
configSpec.Annotations[libpod.InspectAnnotationPrivileged] = libpod.InspectResponseTrue
} else {
configSpec.Annotations[libpod.InspectAnnotationPrivileged] = libpod.InspectResponseFalse
}
- if config.PublishAll {
- configSpec.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseTrue
- } else {
- configSpec.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseFalse
- }
-
if config.Init {
configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseTrue
} else {
configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseFalse
}
- for _, opt := range config.SecurityOpts {
- // Split on both : and =
- splitOpt := strings.Split(opt, "=")
- if len(splitOpt) == 1 {
- splitOpt = strings.Split(opt, ":")
- }
- if len(splitOpt) < 2 {
- continue
- }
- switch splitOpt[0] {
- case "label":
- configSpec.Annotations[libpod.InspectAnnotationLabel] = splitOpt[1]
- case "seccomp":
- configSpec.Annotations[libpod.InspectAnnotationSeccomp] = splitOpt[1]
- case "apparmor":
- configSpec.Annotations[libpod.InspectAnnotationApparmor] = splitOpt[1]
- }
- }
-
return configSpec, nil
}
func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) {
- if !config.Privileged {
+ if !config.Security.Privileged {
for _, mp := range []string{
"/proc/acpi",
"/proc/kcore",
@@ -518,7 +415,7 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator)
g.AddLinuxMaskedPaths(mp)
}
- if config.PidMode.IsHost() && rootless.IsRootless() {
+ if config.Pid.PidMode.IsHost() && rootless.IsRootless() {
return
}
@@ -535,130 +432,6 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator)
}
}
-func addPidNS(config *CreateConfig, g *generate.Generator) error {
- pidMode := config.PidMode
- if IsNS(string(pidMode)) {
- return g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), NS(string(pidMode)))
- }
- if pidMode.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.PIDNamespace))
- }
- if pidCtr := pidMode.Container(); pidCtr != "" {
- logrus.Debugf("using container %s pidmode", pidCtr)
- }
- if IsPod(string(pidMode)) {
- logrus.Debug("using pod pidmode")
- }
- return nil
-}
-
-func addUserNS(config *CreateConfig, g *generate.Generator) error {
- if IsNS(string(config.UsernsMode)) {
- if err := g.AddOrReplaceLinuxNamespace(string(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))
- }
-
- if (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() {
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
- return err
- }
- }
- return nil
-}
-
-func addNetNS(config *CreateConfig, g *generate.Generator) error {
- netMode := config.NetMode
- if netMode.IsHost() {
- logrus.Debug("Using host netmode")
- return g.RemoveLinuxNamespace(string(spec.NetworkNamespace))
- } else if netMode.IsNone() {
- logrus.Debug("Using none netmode")
- return nil
- } else if netMode.IsBridge() {
- logrus.Debug("Using bridge netmode")
- return nil
- } else if netCtr := netMode.Container(); netCtr != "" {
- logrus.Debugf("using container %s netmode", netCtr)
- return nil
- } else if IsNS(string(netMode)) {
- logrus.Debug("Using ns netmode")
- return g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), NS(string(netMode)))
- } else if IsPod(string(netMode)) {
- logrus.Debug("Using pod netmode, unless pod is not sharing")
- return nil
- } else if netMode.IsSlirp4netns() {
- logrus.Debug("Using slirp4netns netmode")
- return nil
- } else if netMode.IsUserDefined() {
- logrus.Debug("Using user defined netmode")
- return nil
- }
- return errors.Errorf("unknown network mode")
-}
-
-func addUTSNS(config *CreateConfig, g *generate.Generator) error {
- utsMode := config.UtsMode
- if IsNS(string(utsMode)) {
- return g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), NS(string(utsMode)))
- }
- if utsMode.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.UTSNamespace))
- }
- if utsCtr := utsMode.Container(); utsCtr != "" {
- logrus.Debugf("using container %s utsmode", utsCtr)
- }
- return nil
-}
-
-func addIpcNS(config *CreateConfig, g *generate.Generator) error {
- ipcMode := config.IpcMode
- if IsNS(string(ipcMode)) {
- return g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), NS(string(ipcMode)))
- }
- if ipcMode.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.IPCNamespace))
- }
- if ipcCtr := ipcMode.Container(); ipcCtr != "" {
- logrus.Debugf("Using container %s ipcmode", ipcCtr)
- }
-
- return nil
-}
-
-func addCgroupNS(config *CreateConfig, g *generate.Generator) error {
- cgroupMode := config.CgroupMode
-
- if cgroupMode.IsDefaultValue() {
- // If the value is not specified, default to "private" on cgroups v2 and "host" on cgroups v1.
- unified, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return err
- }
- if unified {
- cgroupMode = "private"
- } else {
- cgroupMode = "host"
- }
- }
- if cgroupMode.IsNS() {
- return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), NS(string(cgroupMode)))
- }
- if cgroupMode.IsHost() {
- return g.RemoveLinuxNamespace(string(spec.CgroupNamespace))
- }
- if cgroupMode.IsPrivate() {
- return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), "")
- }
- if cgCtr := cgroupMode.Container(); cgCtr != "" {
- logrus.Debugf("Using container %s cgroup mode", cgCtr)
- }
- return nil
-}
-
func addRlimits(config *CreateConfig, g *generate.Generator) error {
var (
kernelMax uint64 = 1048576
@@ -702,37 +475,3 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error {
return nil
}
-
-func setupCapabilities(config *CreateConfig, configSpec *spec.Spec) error {
- useNotRoot := func(user string) bool {
- if user == "" || user == "root" || user == "0" {
- return false
- }
- return true
- }
-
- var err error
- var caplist []string
- bounding := configSpec.Process.Capabilities.Bounding
- if useNotRoot(config.User) {
- configSpec.Process.Capabilities.Bounding = caplist
- }
- caplist, err = caps.TweakCapabilities(configSpec.Process.Capabilities.Bounding, config.CapAdd, config.CapDrop, nil, false)
- if err != nil {
- return err
- }
-
- configSpec.Process.Capabilities.Bounding = caplist
- configSpec.Process.Capabilities.Permitted = caplist
- configSpec.Process.Capabilities.Inheritable = caplist
- configSpec.Process.Capabilities.Effective = caplist
- configSpec.Process.Capabilities.Ambient = caplist
- if useNotRoot(config.User) {
- caplist, err = caps.TweakCapabilities(bounding, config.CapAdd, config.CapDrop, nil, false)
- if err != nil {
- return err
- }
- }
- configSpec.Process.Capabilities.Bounding = caplist
- return nil
-}