summaryrefslogtreecommitdiff
path: root/pkg/spec
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/spec')
-rw-r--r--pkg/spec/spec.go64
-rw-r--r--pkg/spec/spec_linux.go42
-rw-r--r--pkg/spec/spec_unsupported.go7
-rw-r--r--pkg/spec/storage.go7
4 files changed, 109 insertions, 11 deletions
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 06d1ac12d..53b73296a 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -20,6 +20,12 @@ import (
const cpuPeriod = 100000
+type systemUlimit struct {
+ name string
+ max uint64
+ cur uint64
+}
+
func getAvailableGids() (int64, error) {
idMap, err := user.ParseIDMapFile("/proc/self/gid_map")
if err != nil {
@@ -80,23 +86,41 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
g.AddLinuxMaskedPaths("/sys/kernel")
}
}
+ gid5Available := true
if isRootless {
nGids, err := getAvailableGids()
if err != nil {
return nil, err
}
- if nGids < 5 {
- // If we have no GID mappings, the gid=5 default option would fail, so drop it.
- g.RemoveMount("/dev/pts")
- devPts := spec.Mount{
- Destination: "/dev/pts",
- Type: "devpts",
- Source: "devpts",
- Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
+ gid5Available = nGids >= 5
+ }
+ // When using a different user namespace, check that the GID 5 is mapped inside
+ // the container.
+ if gid5Available && len(config.IDMappings.GIDMap) > 0 {
+ mappingFound := false
+ for _, r := range config.IDMappings.GIDMap {
+ if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size {
+ mappingFound = true
+ break
}
- g.AddMount(devPts)
}
+ if !mappingFound {
+ gid5Available = false
+ }
+
+ }
+ if !gid5Available {
+ // If we have no GID mappings, the gid=5 default option would fail, so drop it.
+ g.RemoveMount("/dev/pts")
+ devPts := spec.Mount{
+ Destination: "/dev/pts",
+ Type: "devpts",
+ Source: "devpts",
+ Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
+ }
+ g.AddMount(devPts)
}
+
if inUserNS && config.IpcMode.IsHost() {
g.RemoveMount("/dev/mqueue")
devMqueue := spec.Mount{
@@ -475,7 +499,9 @@ func addPidNS(config *CreateConfig, g *generate.Generator) error {
func addUserNS(config *CreateConfig, g *generate.Generator) error {
if IsNS(string(config.UsernsMode)) {
- g.AddOrReplaceLinuxNamespace(spec.UserNamespace, NS(string(config.UsernsMode)))
+ 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))
@@ -483,7 +509,9 @@ func addUserNS(config *CreateConfig, g *generate.Generator) error {
}
if (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() {
- g.AddOrReplaceLinuxNamespace(spec.UserNamespace, "")
+ if err := g.AddOrReplaceLinuxNamespace(spec.UserNamespace, ""); err != nil {
+ return err
+ }
}
return nil
}
@@ -553,6 +581,20 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error {
)
for _, u := range config.Resources.Ulimit {
+ if u == "host" {
+ if len(config.Resources.Ulimit) != 1 {
+ return errors.New("ulimit can use host only once")
+ }
+ hostLimits, err := getHostRlimits()
+ if err != nil {
+ return err
+ }
+ for _, i := range hostLimits {
+ g.AddProcessRlimits(i.name, i.max, i.cur)
+ }
+ break
+ }
+
ul, err := units.ParseUlimit(u)
if err != nil {
return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u)
diff --git a/pkg/spec/spec_linux.go b/pkg/spec/spec_linux.go
new file mode 100644
index 000000000..fcdfc5c4e
--- /dev/null
+++ b/pkg/spec/spec_linux.go
@@ -0,0 +1,42 @@
+//+build linux
+
+package createconfig
+
+import (
+ "syscall"
+
+ "github.com/pkg/errors"
+)
+
+type systemRlimit struct {
+ name string
+ value int
+}
+
+var systemLimits = []systemRlimit{
+ {"RLIMIT_AS", syscall.RLIMIT_AS},
+ {"RLIMIT_CORE", syscall.RLIMIT_CORE},
+ {"RLIMIT_CPU", syscall.RLIMIT_CPU},
+ {"RLIMIT_DATA", syscall.RLIMIT_DATA},
+ {"RLIMIT_FSIZE", syscall.RLIMIT_FSIZE},
+ {"RLIMIT_NOFILE", syscall.RLIMIT_NOFILE},
+ {"RLIMIT_STACK", syscall.RLIMIT_STACK},
+}
+
+func getHostRlimits() ([]systemUlimit, error) {
+ ret := []systemUlimit{}
+ for _, i := range systemLimits {
+ var l syscall.Rlimit
+ if err := syscall.Getrlimit(i.value, &l); err != nil {
+ return nil, errors.Wrapf(err, "cannot read limits for %s", i.name)
+ }
+ s := systemUlimit{
+ name: i.name,
+ max: l.Max,
+ cur: l.Cur,
+ }
+ ret = append(ret, s)
+ }
+ return ret, nil
+
+}
diff --git a/pkg/spec/spec_unsupported.go b/pkg/spec/spec_unsupported.go
new file mode 100644
index 000000000..0f6a9acdc
--- /dev/null
+++ b/pkg/spec/spec_unsupported.go
@@ -0,0 +1,7 @@
+//+build !linux
+
+package createconfig
+
+func getHostRlimits() ([]systemUlimit, error) {
+ return nil, nil
+}
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index ed767f5ba..88f1f6dc1 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -211,6 +211,13 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
}
mount.Options = opts
}
+ if mount.Type == TypeBind {
+ absSrc, err := filepath.Abs(mount.Source)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
+ }
+ mount.Source = absSrc
+ }
finalMounts = append(finalMounts, mount)
}
finalVolumes := make([]*libpod.ContainerNamedVolume, 0, len(baseVolumes))