summaryrefslogtreecommitdiff
path: root/pkg/spec
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/spec')
-rw-r--r--pkg/spec/config_linux.go55
-rw-r--r--pkg/spec/config_linux_cgo.go11
-rw-r--r--pkg/spec/config_unsupported.go8
-rw-r--r--pkg/spec/createconfig.go85
-rw-r--r--pkg/spec/namespaces.go2
-rw-r--r--pkg/spec/parse.go32
-rw-r--r--pkg/spec/security.go45
-rw-r--r--pkg/spec/spec.go109
-rw-r--r--pkg/spec/storage.go11
9 files changed, 234 insertions, 124 deletions
diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
index 32d8cb4de..544c0020d 100644
--- a/pkg/spec/config_linux.go
+++ b/pkg/spec/config_linux.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "strconv"
"strings"
"github.com/containers/libpod/pkg/rootless"
@@ -31,8 +32,8 @@ func Device(d *configs.Device) spec.LinuxDevice {
}
}
-// devicesFromPath computes a list of devices
-func devicesFromPath(g *generate.Generator, devicePath string) error {
+// DevicesFromPath computes a list of devices
+func DevicesFromPath(g *generate.Generator, devicePath string) error {
devs := strings.Split(devicePath, ":")
resolvedDevicePath := devs[0]
// check if it is a symbolic link
@@ -90,6 +91,42 @@ func devicesFromPath(g *generate.Generator, devicePath string) error {
return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
}
+func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error {
+ for _, deviceCgroupRule := range deviceCgroupRules {
+ if err := validateDeviceCgroupRule(deviceCgroupRule); err != nil {
+ return err
+ }
+ ss := parseDeviceCgroupRule(deviceCgroupRule)
+ if len(ss[0]) != 5 {
+ return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ matches := ss[0]
+ var major, minor *int64
+ if matches[2] == "*" {
+ majorDev := int64(-1)
+ major = &majorDev
+ } else {
+ majorDev, err := strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ major = &majorDev
+ }
+ if matches[3] == "*" {
+ minorDev := int64(-1)
+ minor = &minorDev
+ } else {
+ minorDev, err := strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ minor = &minorDev
+ }
+ g.AddLinuxResourcesDevice(true, matches[1], major, minor, matches[4])
+ }
+ return nil
+}
+
func addDevice(g *generate.Generator, device string) error {
src, dst, permissions, err := ParseDevice(device)
if err != nil {
@@ -179,7 +216,7 @@ func getDevices(path string) ([]*configs.Device, error) {
return out, nil
}
-func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
+func addPrivilegedDevices(g *generate.Generator) error {
hostDevices, err := getDevices("/dev")
if err != nil {
return err
@@ -243,16 +280,16 @@ func (c *CreateConfig) createBlockIO() (*spec.LinuxBlockIO, error) {
var lwds []spec.LinuxWeightDevice
ret = bio
for _, i := range c.Resources.BlkioWeightDevice {
- wd, err := validateweightDevice(i)
+ wd, err := ValidateweightDevice(i)
if err != nil {
return ret, errors.Wrapf(err, "invalid values for blkio-weight-device")
}
- wdStat, err := getStatFromPath(wd.path)
+ wdStat, err := GetStatFromPath(wd.Path)
if err != nil {
- return ret, errors.Wrapf(err, "error getting stat from path %q", wd.path)
+ return ret, errors.Wrapf(err, "error getting stat from path %q", wd.Path)
}
lwd := spec.LinuxWeightDevice{
- Weight: &wd.weight,
+ Weight: &wd.Weight,
}
lwd.Major = int64(unix.Major(wdStat.Rdev))
lwd.Minor = int64(unix.Minor(wdStat.Rdev))
@@ -310,7 +347,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
if err != nil {
return []spec.LinuxThrottleDevice{}, err
}
- ltdStat, err := getStatFromPath(t.path)
+ ltdStat, err := GetStatFromPath(t.path)
if err != nil {
return ltds, errors.Wrapf(err, "error getting stat from path %q", t.path)
}
@@ -324,7 +361,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
return ltds, nil
}
-func getStatFromPath(path string) (unix.Stat_t, error) {
+func GetStatFromPath(path string) (unix.Stat_t, error) {
s := unix.Stat_t{}
err := unix.Stat(path, &s)
return s, err
diff --git a/pkg/spec/config_linux_cgo.go b/pkg/spec/config_linux_cgo.go
index ae83c9d52..05f42c4da 100644
--- a/pkg/spec/config_linux_cgo.go
+++ b/pkg/spec/config_linux_cgo.go
@@ -5,9 +5,10 @@ package createconfig
import (
"io/ioutil"
+ "github.com/containers/libpod/pkg/seccomp"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
- seccomp "github.com/seccomp/containers-golang"
+ goSeccomp "github.com/seccomp/containers-golang"
"github.com/sirupsen/logrus"
)
@@ -15,9 +16,9 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu
var seccompConfig *spec.LinuxSeccomp
var err error
- if config.SeccompPolicy == SeccompPolicyImage && config.SeccompProfileFromImage != "" {
+ if config.SeccompPolicy == seccomp.PolicyImage && config.SeccompProfileFromImage != "" {
logrus.Debug("Loading seccomp profile from the security config")
- seccompConfig, err = seccomp.LoadProfile(config.SeccompProfileFromImage, configSpec)
+ seccompConfig, err = goSeccomp.LoadProfile(config.SeccompProfileFromImage, configSpec)
if err != nil {
return nil, errors.Wrap(err, "loading seccomp profile failed")
}
@@ -30,13 +31,13 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu
if err != nil {
return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath)
}
- seccompConfig, err = seccomp.LoadProfile(string(seccompProfile), configSpec)
+ seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec)
if err != nil {
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
}
} else {
logrus.Debug("Loading default seccomp profile")
- seccompConfig, err = seccomp.GetDefaultProfile(configSpec)
+ seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec)
if err != nil {
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
}
diff --git a/pkg/spec/config_unsupported.go b/pkg/spec/config_unsupported.go
index a2c7f4416..568afde55 100644
--- a/pkg/spec/config_unsupported.go
+++ b/pkg/spec/config_unsupported.go
@@ -15,7 +15,7 @@ func addDevice(g *generate.Generator, device string) error {
return errors.New("function not implemented")
}
-func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
+func addPrivilegedDevices(g *generate.Generator) error {
return errors.New("function not implemented")
}
@@ -27,6 +27,10 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
return nil, errors.New("function not implemented")
}
-func devicesFromPath(g *generate.Generator, devicePath string) error {
+func DevicesFromPath(g *generate.Generator, devicePath string) error {
+ return errors.New("function not implemented")
+}
+
+func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error {
return errors.New("function not implemented")
}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index fb222083b..daa997104 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -2,7 +2,6 @@ package createconfig
import (
"os"
- "sort"
"strconv"
"strings"
"syscall"
@@ -11,6 +10,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/namespaces"
+ "github.com/containers/libpod/pkg/seccomp"
"github.com/containers/storage"
"github.com/docker/go-connections/nat"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -38,6 +38,7 @@ type CreateResourceConfig struct {
CPUs float64 // cpus
CPUsetCPUs string
CPUsetMems string // cpuset-mems
+ DeviceCgroupRules []string //device-cgroup-rule
DeviceReadBps []string // device-read-bps
DeviceReadIOps []string // device-read-iops
DeviceWriteBps []string // device-write-bps
@@ -107,58 +108,17 @@ type NetworkConfig struct {
PublishAll bool //publish-all
}
-// SeccompPolicy determines which seccomp profile gets applied to the container.
-type SeccompPolicy int
-
-const (
- // SeccompPolicyDefault - if set use SecurityConfig.SeccompProfilePath,
- // otherwise use the default profile. The SeccompProfilePath might be
- // explicitly set by the user.
- SeccompPolicyDefault SeccompPolicy = iota
- // SeccompPolicyImage - if set use SecurityConfig.SeccompProfileFromImage,
- // otherwise follow SeccompPolicyDefault.
- SeccompPolicyImage
-)
-
-// Map for easy lookups of supported policies.
-var supportedSeccompPolicies = map[string]SeccompPolicy{
- "": SeccompPolicyDefault,
- "default": SeccompPolicyDefault,
- "image": SeccompPolicyImage,
-}
-
-// LookupSeccompPolicy looksup the corresponding SeccompPolicy for the specified
-// string. If none is found, an errors is returned including the list of
-// supported policies.
-// Note that an empty string resolved to SeccompPolicyDefault.
-func LookupSeccompPolicy(s string) (SeccompPolicy, error) {
- policy, exists := supportedSeccompPolicies[s]
- if exists {
- return policy, nil
- }
-
- // Sort the keys first as maps are non-deterministic.
- keys := []string{}
- for k := range supportedSeccompPolicies {
- if k != "" {
- keys = append(keys, k)
- }
- }
- sort.Strings(keys)
-
- return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys)
-}
-
// SecurityConfig configures the security features for the container
type SecurityConfig struct {
CapAdd []string // cap-add
CapDrop []string // cap-drop
+ CapRequired []string // cap-required
LabelOpts []string //SecurityOpts
NoNewPrivs bool //SecurityOpts
ApparmorProfile string //SecurityOpts
SeccompProfilePath string //SecurityOpts
SeccompProfileFromImage string // seccomp profile from the container image
- SeccompPolicy SeccompPolicy
+ SeccompPolicy seccomp.Policy
SecurityOpts []string
Privileged bool //privileged
ReadOnlyRootfs bool //read-only
@@ -167,6 +127,7 @@ type SecurityConfig struct {
}
// CreateConfig is a pre OCI spec structure. It represents user input from varlink or the CLI
+// swagger:model CreateConfig
type CreateConfig struct {
Annotations map[string]string
Args []string
@@ -183,6 +144,7 @@ type CreateConfig struct {
InitPath string //init-path
Image string
ImageID string
+ RawImageName string
BuiltinImgVolumes map[string]struct{} // volumes defined in the image config
ImageVolumeType string // how to handle the image volume, either bind, tmpfs, or ignore
Interactive bool //interactive
@@ -196,6 +158,7 @@ type CreateConfig struct {
Resources CreateResourceConfig
RestartPolicy string
Rm bool //rm
+ Rmi bool //rmi
StopSignal syscall.Signal // stop-signal
StopTimeout uint // stop-timeout
Systemd bool
@@ -233,6 +196,7 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err
if err != nil {
return nil, err
}
+ storageConfig := runtime.StorageConfig()
// We need a cleanup process for containers in the current model.
// But we can't assume that the caller is Podman - it could be another
@@ -245,23 +209,23 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err
}
command := []string{cmd,
- "--root", config.StorageConfig.GraphRoot,
- "--runroot", config.StorageConfig.RunRoot,
+ "--root", storageConfig.GraphRoot,
+ "--runroot", storageConfig.RunRoot,
"--log-level", logrus.GetLevel().String(),
- "--cgroup-manager", config.CgroupManager,
- "--tmpdir", config.TmpDir,
+ "--cgroup-manager", config.Engine.CgroupManager,
+ "--tmpdir", config.Engine.TmpDir,
}
- if config.OCIRuntime != "" {
- command = append(command, []string{"--runtime", config.OCIRuntime}...)
+ if config.Engine.OCIRuntime != "" {
+ command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...)
}
- if config.StorageConfig.GraphDriverName != "" {
- command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...)
+ if storageConfig.GraphDriverName != "" {
+ command = append(command, []string{"--storage-driver", storageConfig.GraphDriverName}...)
}
- for _, opt := range config.StorageConfig.GraphDriverOptions {
+ for _, opt := range storageConfig.GraphDriverOptions {
command = append(command, []string{"--storage-opt", opt}...)
}
- if config.EventsLogger != "" {
- command = append(command, []string{"--events-backend", config.EventsLogger}...)
+ if config.Engine.EventsLogger != "" {
+ command = append(command, []string{"--events-backend", config.Engine.EventsLogger}...)
}
if c.Syslog {
@@ -273,6 +237,10 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err
command = append(command, "--rm")
}
+ if c.Rmi {
+ command = append(command, "--rmi")
+ }
+
return command, nil
}
@@ -381,9 +349,8 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l
}
options = append(options, nsOpts...)
- useImageVolumes := c.ImageVolumeType == TypeBind
// Gather up the options for NewContainer which consist of With... funcs
- options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image, useImageVolumes))
+ options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image, c.RawImageName))
options = append(options, libpod.WithConmonPidFile(c.ConmonPidFile))
options = append(options, libpod.WithLabels(c.Labels))
options = append(options, libpod.WithShmSize(c.Resources.ShmSize))
@@ -427,6 +394,6 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l
// AddPrivilegedDevices iterates through host devices and adds all
// host devices to the spec
-func (c *CreateConfig) AddPrivilegedDevices(g *generate.Generator) error {
- return c.addPrivilegedDevices(g)
+func AddPrivilegedDevices(g *generate.Generator) error {
+ return addPrivilegedDevices(g)
}
diff --git a/pkg/spec/namespaces.go b/pkg/spec/namespaces.go
index 1f98e6e25..838d95c54 100644
--- a/pkg/spec/namespaces.go
+++ b/pkg/spec/namespaces.go
@@ -422,7 +422,7 @@ func (c *UtsConfig) ConfigureGenerator(g *generate.Generator, net *NetworkConfig
if hostname == "" {
switch {
case utsCtrID != "":
- utsCtr, err := runtime.GetContainer(utsCtrID)
+ utsCtr, err := runtime.LookupContainer(utsCtrID)
if err != nil {
return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", utsCtrID)
}
diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go
index 6fa0b0636..38d93b87f 100644
--- a/pkg/spec/parse.go
+++ b/pkg/spec/parse.go
@@ -2,24 +2,29 @@ package createconfig
import (
"fmt"
+ "regexp"
"strconv"
"strings"
"github.com/docker/go-units"
+ "github.com/pkg/errors"
)
+// deviceCgroupRulegex defines the valid format of device-cgroup-rule
+var deviceCgroupRuleRegex = regexp.MustCompile(`^([acb]) ([0-9]+|\*):([0-9]+|\*) ([rwm]{1,3})$`)
+
// Pod signifies a kernel namespace is being shared
// by a container with the pod it is associated with
const Pod = "pod"
// weightDevice is a structure that holds device:weight pair
type weightDevice struct {
- path string
- weight uint16
+ Path string
+ Weight uint16
}
func (w *weightDevice) String() string {
- return fmt.Sprintf("%s:%d", w.path, w.weight)
+ return fmt.Sprintf("%s:%d", w.Path, w.Weight)
}
// LinuxNS is a struct that contains namespace information
@@ -54,9 +59,9 @@ func NS(s string) string {
return ""
}
-// validateweightDevice validates that the specified string has a valid device-weight format
+// ValidateweightDevice validates that the specified string has a valid device-weight format
// for blkio-weight-device flag
-func validateweightDevice(val string) (*weightDevice, error) {
+func ValidateweightDevice(val string) (*weightDevice, error) {
split := strings.SplitN(val, ":", 2)
if len(split) != 2 {
return nil, fmt.Errorf("bad format: %s", val)
@@ -73,8 +78,8 @@ func validateweightDevice(val string) (*weightDevice, error) {
}
return &weightDevice{
- path: split[0],
- weight: uint16(weight),
+ Path: split[0],
+ Weight: uint16(weight),
}, nil
}
@@ -205,3 +210,16 @@ func IsValidDeviceMode(mode string) bool {
}
return true
}
+
+// validateDeviceCgroupRule validates the format of deviceCgroupRule
+func validateDeviceCgroupRule(deviceCgroupRule string) error {
+ if !deviceCgroupRuleRegex.MatchString(deviceCgroupRule) {
+ return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ return nil
+}
+
+// parseDeviceCgroupRule matches and parses the deviceCgroupRule into slice
+func parseDeviceCgroupRule(deviceCgroupRule string) [][]string {
+ return deviceCgroupRuleRegex.FindAllStringSubmatch(deviceCgroupRule, -1)
+}
diff --git a/pkg/spec/security.go b/pkg/spec/security.go
index 372fe87c6..0f8d36f00 100644
--- a/pkg/spec/security.go
+++ b/pkg/spec/security.go
@@ -4,11 +4,13 @@ import (
"fmt"
"strings"
+ "github.com/containers/common/pkg/capabilities"
"github.com/containers/libpod/libpod"
- "github.com/docker/docker/oci/caps"
+ "github.com/containers/libpod/pkg/util"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// ToCreateOptions convert the SecurityConfig to a slice of container create
@@ -113,28 +115,49 @@ func (c *SecurityConfig) ConfigureGenerator(g *generate.Generator, user *UserCon
configSpec := g.Config
var err error
- var caplist []string
+ var defaultCaplist []string
bounding := configSpec.Process.Capabilities.Bounding
if useNotRoot(user.User) {
- configSpec.Process.Capabilities.Bounding = caplist
+ configSpec.Process.Capabilities.Bounding = defaultCaplist
}
- caplist, err = caps.TweakCapabilities(configSpec.Process.Capabilities.Bounding, c.CapAdd, c.CapDrop, nil, false)
+ defaultCaplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, c.CapAdd, c.CapDrop)
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
+ privCapRequired := []string{}
+
+ if !c.Privileged && len(c.CapRequired) > 0 {
+ // Pass CapRequired in CapAdd field to normalize capabilities names
+ capRequired, err := capabilities.MergeCapabilities(nil, c.CapRequired, nil)
+ if err != nil {
+ logrus.Errorf("capabilities requested by user or image are not valid: %q", strings.Join(c.CapRequired, ","))
+ } else {
+ // Verify all capRequiered are in the defaultCapList
+ for _, cap := range capRequired {
+ if !util.StringInSlice(cap, defaultCaplist) {
+ privCapRequired = append(privCapRequired, cap)
+ }
+ }
+ }
+ if len(privCapRequired) == 0 {
+ defaultCaplist = capRequired
+ } else {
+ logrus.Errorf("capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapRequired, ","))
+ }
+ }
+ configSpec.Process.Capabilities.Bounding = defaultCaplist
+ configSpec.Process.Capabilities.Permitted = defaultCaplist
+ configSpec.Process.Capabilities.Inheritable = defaultCaplist
+ configSpec.Process.Capabilities.Effective = defaultCaplist
+ configSpec.Process.Capabilities.Ambient = defaultCaplist
if useNotRoot(user.User) {
- caplist, err = caps.TweakCapabilities(bounding, c.CapAdd, c.CapDrop, nil, false)
+ defaultCaplist, err = capabilities.MergeCapabilities(bounding, c.CapAdd, c.CapDrop)
if err != nil {
return err
}
}
- configSpec.Process.Capabilities.Bounding = caplist
+ configSpec.Process.Capabilities.Bounding = defaultCaplist
// HANDLE SECCOMP
if c.SeccompProfilePath != "unconfined" {
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index cae055bb0..d4fd5976f 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -3,12 +3,14 @@ package createconfig
import (
"strings"
+ "github.com/containers/common/pkg/capabilities"
+ cconfig "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod"
- libpodconfig "github.com/containers/libpod/libpod/config"
- "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/cgroups"
+ "github.com/containers/libpod/pkg/env"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/sysinfo"
+ "github.com/containers/libpod/pkg/util"
"github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -16,9 +18,9 @@ import (
"github.com/pkg/errors"
)
-const cpuPeriod = 100000
+const CpuPeriod = 100000
-func getAvailableGids() (int64, error) {
+func GetAvailableGids() (int64, error) {
idMap, err := user.ParseIDMapFile("/proc/self/gid_map")
if err != nil {
return 0, err
@@ -78,9 +80,40 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
g.AddLinuxMaskedPaths("/sys/kernel")
}
}
+ var runtimeConfig *cconfig.Config
+
+ if runtime != nil {
+ runtimeConfig, err = runtime.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ g.Config.Process.Capabilities.Bounding = runtimeConfig.Containers.DefaultCapabilities
+ sysctls, err := util.ValidateSysctls(runtimeConfig.Containers.DefaultSysctls)
+ if err != nil {
+ return nil, err
+ }
+
+ for name, val := range config.Security.Sysctl {
+ sysctls[name] = val
+ }
+ config.Security.Sysctl = sysctls
+ if !util.StringInSlice("host", config.Resources.Ulimit) {
+ config.Resources.Ulimit = append(runtimeConfig.Containers.DefaultUlimits, config.Resources.Ulimit...)
+ }
+ if config.Resources.PidsLimit < 0 && !config.cgroupDisabled() {
+ config.Resources.PidsLimit = runtimeConfig.Containers.PidsLimit
+ }
+
+ } else {
+ g.Config.Process.Capabilities.Bounding = cconfig.DefaultCapabilities
+ if config.Resources.PidsLimit < 0 && !config.cgroupDisabled() {
+ config.Resources.PidsLimit = cconfig.DefaultPidsLimit
+ }
+ }
+
gid5Available := true
if isRootless {
- nGids, err := getAvailableGids()
+ nGids, err := GetAvailableGids()
if err != nil {
return nil, err
}
@@ -150,7 +183,6 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
for key, val := range config.Annotations {
g.AddAnnotation(key, val)
}
- g.AddProcessEnv("container", "podman")
addedResources := false
@@ -197,8 +229,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
addedResources = true
}
if config.Resources.CPUs != 0 {
- g.SetLinuxResourcesCPUPeriod(cpuPeriod)
- g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * cpuPeriod))
+ g.SetLinuxResourcesCPUPeriod(CpuPeriod)
+ g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * CpuPeriod))
addedResources = true
}
if config.Resources.CPURtRuntime != 0 {
@@ -223,35 +255,43 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
// 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.
- if err := config.AddPrivilegedDevices(&g); err != nil {
+ if err := AddPrivilegedDevices(&g); err != nil {
return nil, err
}
} else {
for _, devicePath := range config.Devices {
- if err := devicesFromPath(&g, devicePath); err != nil {
+ if err := DevicesFromPath(&g, devicePath); err != nil {
return nil, err
}
}
+ if len(config.Resources.DeviceCgroupRules) != 0 {
+ if err := deviceCgroupRules(&g, config.Resources.DeviceCgroupRules); err != nil {
+ return nil, err
+ }
+ addedResources = true
+ }
}
- // SECURITY OPTS
g.SetProcessNoNewPrivileges(config.Security.NoNewPrivs)
if !config.Security.Privileged {
g.SetProcessApparmorProfile(config.Security.ApparmorProfile)
}
- blockAccessToKernelFilesystems(config, &g)
-
- var runtimeConfig *libpodconfig.Config
-
- if runtime != nil {
- runtimeConfig, err = runtime.GetConfig()
- if err != nil {
+ // Unless already set via the CLI, check if we need to disable process
+ // labels or set the defaults.
+ if len(config.Security.LabelOpts) == 0 && runtimeConfig != nil {
+ if !runtimeConfig.Containers.EnableLabeling {
+ // Disabled in the config.
+ config.Security.LabelOpts = append(config.Security.LabelOpts, "disable")
+ } else if err := config.Security.SetLabelOpts(runtime, &config.Pid, &config.Ipc); err != nil {
+ // Defaults!
return nil, err
}
}
+ BlockAccessToKernelFilesystems(config.Security.Privileged, config.Pid.PidMode.IsHost(), &g)
+
// RESOURCES - PIDS
if config.Resources.PidsLimit > 0 {
// if running on rootless on a cgroupv1 machine or using the cgroupfs manager, pids
@@ -264,7 +304,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
if err != nil {
return nil, err
}
- if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.CgroupManager != define.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() {
+ if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.Engine.CgroupManager != cconfig.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() {
setPidLimit = false
}
}
@@ -274,6 +314,9 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
}
+ // Make sure to always set the default variables unless overridden in the
+ // config.
+ config.Env = env.Join(env.DefaultEnvVariables, config.Env)
for name, val := range config.Env {
g.AddProcessEnv(name, val)
}
@@ -309,14 +352,26 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
configSpec := g.Config
+ // If the container image specifies an label with a
+ // capabilities.ContainerImageLabel then split the comma separated list
+ // of capabilities and record them. This list indicates the only
+ // capabilities, required to run the container.
+ var capRequired []string
+ for key, val := range config.Labels {
+ if util.StringInSlice(key, capabilities.ContainerImageLabels) {
+ capRequired = strings.Split(val, ",")
+ }
+ }
+ config.Security.CapRequired = capRequired
+
if err := config.Security.ConfigureGenerator(&g, &config.User); err != nil {
return nil, err
}
// BIND MOUNTS
- configSpec.Mounts = supercedeUserMounts(userMounts, configSpec.Mounts)
+ configSpec.Mounts = SupercedeUserMounts(userMounts, configSpec.Mounts)
// Process mounts to ensure correct options
- finalMounts, err := initFSMounts(configSpec.Mounts)
+ finalMounts, err := InitFSMounts(configSpec.Mounts)
if err != nil {
return nil, err
}
@@ -341,7 +396,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
configSpec.Linux.Resources = &spec.LinuxResources{}
}
- canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.CgroupManager == define.SystemdCgroupsManager)
+ canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.Engine.CgroupManager == cconfig.SystemdCgroupsManager)
if addedResources && !canUseResources {
return nil, errors.New("invalid configuration, cannot specify resource limits without cgroups v2 and --cgroup-manager=systemd")
@@ -398,8 +453,12 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
return configSpec, nil
}
-func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) {
- if !config.Security.Privileged {
+func (config *CreateConfig) cgroupDisabled() bool {
+ return config.Cgroup.Cgroups == "disabled"
+}
+
+func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate.Generator) {
+ if !privileged {
for _, mp := range []string{
"/proc/acpi",
"/proc/kcore",
@@ -415,7 +474,7 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator)
g.AddLinuxMaskedPaths(mp)
}
- if config.Pid.PidMode.IsHost() && rootless.IsRootless() {
+ if pidModeIsHost && rootless.IsRootless() {
return
}
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index 0e2098c1d..b0687b4c2 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -124,7 +124,7 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
if err != nil {
return nil, nil, err
}
- initPath = rtc.InitPath
+ initPath = rtc.Engine.InitPath
}
initMount, err := config.addContainerInitBinary(initPath)
if err != nil {
@@ -739,6 +739,7 @@ func (config *CreateConfig) getImageVolumes() (map[string]spec.Mount, map[string
for vol := range config.BuiltinImgVolumes {
cleanDest := filepath.Clean(vol)
+ logrus.Debugf("Adding image volume at %s", cleanDest)
if config.ImageVolumeType == "tmpfs" {
// Tmpfs image volumes are handled as mounts
mount := spec.Mount{
@@ -747,13 +748,13 @@ func (config *CreateConfig) getImageVolumes() (map[string]spec.Mount, map[string
Type: TypeTmpfs,
Options: []string{"rprivate", "rw", "nodev", "exec"},
}
- mounts[vol] = mount
+ mounts[cleanDest] = mount
} else {
// Anonymous volumes have no name.
namedVolume := new(libpod.ContainerNamedVolume)
namedVolume.Options = []string{"rprivate", "rw", "nodev", "exec"}
namedVolume.Dest = cleanDest
- volumes[vol] = namedVolume
+ volumes[cleanDest] = namedVolume
}
}
@@ -825,7 +826,7 @@ func (config *CreateConfig) addContainerInitBinary(path string) (spec.Mount, err
// TODO: Should we unmount subtree mounts? E.g., if /tmp/ is mounted by
// one mount, and we already have /tmp/a and /tmp/b, should we remove
// the /tmp/a and /tmp/b mounts in favor of the more general /tmp?
-func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount {
+func SupercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount {
if len(mounts) > 0 {
// If we have overlappings mounts, remove them from the spec in favor of
// the user-added volume mounts
@@ -854,7 +855,7 @@ func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.M
}
// Ensure mount options on all mounts are correct
-func initFSMounts(inputMounts []spec.Mount) ([]spec.Mount, error) {
+func InitFSMounts(inputMounts []spec.Mount) ([]spec.Mount, error) {
// We need to look up mounts so we can figure out the proper mount flags
// to apply.
systemMounts, err := pmount.GetMounts()