From 650f95cb06cb5a4e979fbe9f9fcd125a229e4e09 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 4 Dec 2018 11:46:17 -0800 Subject: libpod/container_internal_linux: Allow gids that aren't in the group file When an image config sets config.User [1] to a numeric group (like 1000:1000), but those values do not exist in the container's /etc/group, libpod is currently breaking: $ podman run --rm registry.svc.ci.openshift.org/ci-op-zvml7cd6/pipeline:installer --help error creating temporary passwd file for container 228f6e9943d6f18b93c19644e9b619ec4d459a3e0eb31680e064eeedf6473678: unable to get gid 1000 from group file: no matching entries in group file However, the OCI spec requires converters to copy numeric uid and gid to the runtime config verbatim [2]. With this commit, I'm frontloading the "is groupspec an integer?" check and only bothering with lookup.GetGroup when it was not. I've also removed a few .Mounted checks, which are originally from 00d38cb3 (podman create/run need to load information from the image, 2017-12-18, #110). We don't need a mounted container filesystem to translate integers. And when the lookup code needs to fall back to the mounted root to translate names, it can handle erroring out internally (and looking it over, it seems to do that already). [1]: https://github.com/opencontainers/image-spec/blame/v1.0.1/config.md#L118-L123 [2]: https://github.com/opencontainers/image-spec/blame/v1.0.1/conversion.md#L70 Signed-off-by: W. Trevor King --- libpod/container_internal_linux.go | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 8861d7728..b72eefdf1 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -238,9 +238,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } if c.config.User != "" { - if !c.state.Mounted { - return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to translate User field", c.ID()) - } // User and Group must go together g.SetProcessUID(uint32(execUser.Uid)) g.SetProcessGID(uint32(execUser.Gid)) @@ -248,9 +245,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Add addition groups if c.config.GroupAdd is not empty if len(c.config.Groups) > 0 { - if !c.state.Mounted { - return nil, errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to add additional groups", c.ID()) - } gids, _ := lookup.GetContainerGroups(c.config.Groups, c.state.Mountpoint, nil) for _, gid := range gids { g.AddProcessAdditionalGid(gid) @@ -802,7 +796,6 @@ func (c *Container) generateHosts() (string, error) { func (c *Container) generatePasswd() (string, error) { var ( groupspec string - group *user.Group gid int ) if c.config.User == "" { @@ -827,17 +820,16 @@ func (c *Container) generatePasswd() (string, error) { return "", nil } if groupspec != "" { - if !c.state.Mounted { - return "", errors.Wrapf(ErrCtrStateInvalid, "container %s must be mounted in order to translate group field for passwd record", c.ID()) - } - group, err = lookup.GetGroup(c.state.Mountpoint, groupspec) - if err != nil { - if err == user.ErrNoGroupEntries { + ugid, err := strconv.ParseUint(groupspec, 10, 32) + if err == nil { + gid = int(ugid) + } else { + group, err := lookup.GetGroup(c.state.Mountpoint, groupspec) + if err != nil { return "", errors.Wrapf(err, "unable to get gid %s from group file", groupspec) } - return "", err + gid = group.Gid } - gid = group.Gid } originPasswdFile := filepath.Join(c.state.Mountpoint, "/etc/passwd") orig, err := ioutil.ReadFile(originPasswdFile) -- cgit v1.2.3-54-g00ecf