diff options
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r-- | libpod/container_internal_linux.go | 126 |
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() |