diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2018-10-09 07:54:37 -0400 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2018-10-12 07:08:13 -0400 |
commit | 04a537756d9b7b526759c02b5b5d68c135b210ea (patch) | |
tree | 49e8a0e7610af0b6b752d28262ef78e98e0849b3 /libpod/container_internal.go | |
parent | da5c89497f9d6ee5cb6e826d7db7cca5686ab4f7 (diff) | |
download | podman-04a537756d9b7b526759c02b5b5d68c135b210ea.tar.gz podman-04a537756d9b7b526759c02b5b5d68c135b210ea.tar.bz2 podman-04a537756d9b7b526759c02b5b5d68c135b210ea.zip |
Generate a passwd file for users not in container
If someone runs podman as a user (uid) that is not defined in the container
we want generate a passwd file so that getpwuid() will work inside of container.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r-- | libpod/container_internal.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 77bba9e85..ab79aa790 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strconv" "strings" "syscall" @@ -946,6 +947,19 @@ func (c *Container) makeBindMounts() error { } c.state.BindMounts["/etc/resolv.conf"] = newResolv + newPasswd, err := c.generatePasswd() + if err != nil { + return errors.Wrapf(err, "error creating temporary passwd file for container %s", c.ID()) + } + if newPasswd != "" { + // Make /etc/passwd + if _, ok := c.state.BindMounts["/etc/passwd"]; ok { + // If it already exists, delete so we can recreate + delete(c.state.BindMounts, "/etc/passwd") + } + logrus.Debugf("adding entry to /etc/passwd for non existent default user") + c.state.BindMounts["/etc/passwd"] = newPasswd + } // Make /etc/hosts if _, ok := c.state.BindMounts["/etc/hosts"]; ok { // If it already exists, delete so we can recreate @@ -1017,6 +1031,58 @@ func (c *Container) writeStringToRundir(destFile, output string) (string, error) return filepath.Join(c.state.DestinationRunDir, destFile), nil } +// generatePasswd generates a container specific passwd file, +// iff g.config.User is a number +func (c *Container) generatePasswd() (string, error) { + var ( + groupspec string + gid uint32 + ) + if c.config.User == "" { + return "", nil + } + spec := strings.SplitN(c.config.User, ":", 2) + userspec := spec[0] + if len(spec) > 1 { + groupspec = spec[1] + } + // If a non numeric User, then don't generate passwd + uid, err := strconv.ParseUint(userspec, 10, 32) + if err != nil { + return "", nil + } + // if UID exists inside of container rootfs /etc/passwd then + // don't generate passwd + if _, _, err := chrootuser.LookupUIDInContainer(c.state.Mountpoint, uid); err == nil { + return "", nil + } + if err == nil && 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()) + } + gid, err = chrootuser.GetGroup(c.state.Mountpoint, groupspec) + if err != nil { + return "", errors.Wrapf(err, "unable to get gid from %s formporary passwd file") + } + } + + originPasswdFile := filepath.Join(c.state.Mountpoint, "/etc/passwd") + orig, err := ioutil.ReadFile(originPasswdFile) + if err != nil { + return "", errors.Wrapf(err, "unable to read passwd file %s", originPasswdFile) + } + + pwd := fmt.Sprintf("%s%d:x:%d:%d:container user:%s:/bin/sh\n", orig, uid, uid, gid, c.WorkingDir()) + passwdFile, err := c.writeStringToRundir("passwd", pwd) + if err != nil { + return "", errors.Wrapf(err, "failed to create temporary passwd fileo") + } + if os.Chmod(passwdFile, 0644); err != nil { + return "", err + } + return passwdFile, nil +} + // generateResolvConf generates a containers resolv.conf func (c *Container) generateResolvConf() (string, error) { // Determine the endpoint for resolv.conf in case it is a symlink |