summaryrefslogtreecommitdiff
path: root/libpod/container_internal_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r--libpod/container_internal_linux.go126
1 files changed, 77 insertions, 49 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 3583f8fdd..dc0418148 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -21,22 +21,25 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
+ "github.com/containers/buildah/pkg/chrootuser"
"github.com/containers/buildah/pkg/overlay"
+ butil "github.com/containers/buildah/util"
"github.com/containers/common/pkg/apparmor"
+ "github.com/containers/common/pkg/chown"
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/subscriptions"
"github.com/containers/common/pkg/umask"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/libpod/events"
- "github.com/containers/podman/v2/pkg/annotations"
- "github.com/containers/podman/v2/pkg/cgroups"
- "github.com/containers/podman/v2/pkg/criu"
- "github.com/containers/podman/v2/pkg/lookup"
- "github.com/containers/podman/v2/pkg/resolvconf"
- "github.com/containers/podman/v2/pkg/rootless"
- "github.com/containers/podman/v2/pkg/util"
- "github.com/containers/podman/v2/utils"
- "github.com/containers/podman/v2/version"
+ "github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/libpod/events"
+ "github.com/containers/podman/v3/pkg/annotations"
+ "github.com/containers/podman/v3/pkg/cgroups"
+ "github.com/containers/podman/v3/pkg/criu"
+ "github.com/containers/podman/v3/pkg/lookup"
+ "github.com/containers/podman/v3/pkg/resolvconf"
+ "github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/util"
+ "github.com/containers/podman/v3/utils"
+ "github.com/containers/podman/v3/version"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/idtools"
securejoin "github.com/cyphar/filepath-securejoin"
@@ -203,10 +206,17 @@ func (c *Container) resolveWorkDir() error {
}
logrus.Debugf("Workdir %q resolved to host path %q", workdir, resolvedWorkdir)
- // No need to create it (e.g., `--workdir=/foo`), so let's make sure
- // the path exists on the container.
+ st, err := os.Stat(resolvedWorkdir)
+ if err == nil {
+ if !st.IsDir() {
+ return errors.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID())
+ }
+ return nil
+ }
if !c.config.CreateWorkingDir {
- if _, err := os.Stat(resolvedWorkdir); err != nil {
+ // No need to create it (e.g., `--workdir=/foo`), so let's make sure
+ // the path exists on the container.
+ if err != nil {
if os.IsNotExist(err) {
return errors.Errorf("workdir %q does not exist on container %s", workdir, c.ID())
}
@@ -216,11 +226,6 @@ func (c *Container) resolveWorkDir() error {
}
return nil
}
-
- // Ensure container entrypoint is created (if required).
- rootUID := c.RootUID()
- rootGID := c.RootGID()
-
if err := os.MkdirAll(resolvedWorkdir, 0755); err != nil {
if os.IsExist(err) {
return nil
@@ -228,7 +233,12 @@ func (c *Container) resolveWorkDir() error {
return errors.Wrapf(err, "error creating container %s workdir", c.ID())
}
- if err := os.Chown(resolvedWorkdir, rootUID, rootGID); err != nil {
+ // Ensure container entrypoint is created (if required).
+ uid, gid, _, err := chrootuser.GetUser(c.state.Mountpoint, c.User())
+ if err != nil {
+ return errors.Wrapf(err, "error looking up %s inside of the container %s", c.User(), c.ID())
+ }
+ if err := os.Chown(resolvedWorkdir, int(uid), int(gid)); err != nil {
return errors.Wrapf(err, "error chowning container %s workdir to container root", c.ID())
}
@@ -348,13 +358,28 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, err
}
- // Check if the spec file mounts contain the label Relabel flags z or Z.
- // If they do, relabel the source directory and then remove the option.
+ // Get host UID and GID based on the container process UID and GID.
+ hostUID, hostGID, err := butil.GetHostIDs(util.IDtoolsToRuntimeSpec(c.config.IDMappings.UIDMap), util.IDtoolsToRuntimeSpec(c.config.IDMappings.GIDMap), uint32(execUser.Uid), uint32(execUser.Gid))
+ if err != nil {
+ return nil, err
+ }
+
+ // Check if the spec file mounts contain the options z, Z or U.
+ // If they have z or Z, relabel the source directory and then remove the option.
+ // If they have U, chown the source directory and them remove the option.
for i := range g.Config.Mounts {
m := &g.Config.Mounts[i]
var options []string
for _, o := range m.Options {
switch o {
+ case "U":
+ if m.Type == "tmpfs" {
+ options = append(options, []string{fmt.Sprintf("uid=%d", execUser.Uid), fmt.Sprintf("gid=%d", execUser.Gid)}...)
+ } else {
+ if err := chown.ChangeHostPathOwnership(m.Source, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+ }
case "z":
fallthrough
case "Z":
@@ -419,6 +444,21 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, errors.Wrapf(err, "mounting overlay failed %q", overlayVol.Source)
}
+
+ // Check overlay volume options
+ for _, o := range overlayVol.Options {
+ switch o {
+ case "U":
+ if err := chown.ChangeHostPathOwnership(overlayVol.Source, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+
+ if err := chown.ChangeHostPathOwnership(contentDir, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+ }
+ }
+
g.AddMount(overlayMount)
}
@@ -458,7 +498,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
break
}
}
- if !hasHomeSet {
+ if !hasHomeSet && execUser.Home != "" {
c.config.Spec.Process.Env = append(c.config.Spec.Process.Env, fmt.Sprintf("HOME=%s", execUser.Home))
}
@@ -521,14 +561,14 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}}
}
for _, gid := range execUser.Sgids {
- isGidAvailable := false
+ isGIDAvailable := false
for _, m := range gidMappings {
if gid >= m.ContainerID && gid < m.ContainerID+m.Size {
- isGidAvailable = true
+ isGIDAvailable = true
break
}
}
- if isGidAvailable {
+ if isGIDAvailable {
g.AddProcessAdditionalGid(uint32(gid))
} else {
logrus.Warnf("additional gid=%d is not present in the user namespace, skip setting it", gid)
@@ -1614,13 +1654,12 @@ func (c *Container) makeBindMounts() error {
return errors.Wrapf(err, "error setting timezone for container %s", c.ID())
}
c.state.BindMounts["/etc/localtime"] = localtimePath
-
}
}
// Make .containerenv if it does not exist
if _, ok := c.state.BindMounts["/run/.containerenv"]; !ok {
- var containerenv string
+ containerenv := c.runtime.graphRootMountedFlag(c.config.Spec.Mounts)
isRootless := 0
if rootless.IsRootless() {
isRootless = 1
@@ -1635,7 +1674,7 @@ id=%q
image=%q
imageid=%q
rootless=%d
-`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless)
+%s`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless, containerenv)
}
containerenvPath, err := c.writeStringToRundir(".containerenv", containerenv)
if err != nil {
@@ -1674,8 +1713,9 @@ rootless=%d
// generateResolvConf generates a containers resolv.conf
func (c *Container) generateResolvConf() (string, error) {
var (
- nameservers []string
- cniNameServers []string
+ nameservers []string
+ cniNameServers []string
+ cniSearchDomains []string
)
resolvConf := "/etc/resolv.conf"
@@ -1727,6 +1767,10 @@ func (c *Container) generateResolvConf() (string, error) {
cniNameServers = append(cniNameServers, i.DNS.Nameservers...)
logrus.Debugf("adding nameserver(s) from cni response of '%q'", i.DNS.Nameservers)
}
+ if i.DNS.Search != nil {
+ cniSearchDomains = append(cniSearchDomains, i.DNS.Search...)
+ logrus.Debugf("adding search domain(s) from cni response of '%q'", i.DNS.Search)
+ }
}
dns := make([]net.IP, 0, len(c.runtime.config.Containers.DNSServers))
@@ -1758,10 +1802,11 @@ func (c *Container) generateResolvConf() (string, error) {
}
var search []string
- if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 {
+ if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 || len(cniSearchDomains) > 0 {
if !util.StringInSlice(".", c.config.DNSSearch) {
search = c.runtime.config.Containers.DNSSearches
search = append(search, c.config.DNSSearch...)
+ search = append(search, cniSearchDomains...)
}
} else {
search = resolvconf.GetSearchDomains(resolv.Content)
@@ -2278,23 +2323,6 @@ func (c *Container) generatePasswdAndGroup() (string, string, error) {
return passwdPath, groupPath, nil
}
-func (c *Container) copyOwnerAndPerms(source, dest string) error {
- info, err := os.Stat(source)
- if err != nil {
- if os.IsNotExist(err) {
- return nil
- }
- return err
- }
- if err := os.Chmod(dest, info.Mode()); err != nil {
- return err
- }
- if err := os.Chown(dest, int(info.Sys().(*syscall.Stat_t).Uid), int(info.Sys().(*syscall.Stat_t).Gid)); err != nil {
- return err
- }
- return nil
-}
-
// Get cgroup path in a format suitable for the OCI spec
func (c *Container) getOCICgroupPath() (string, error) {
unified, err := cgroups.IsCgroup2UnifiedMode()