summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2018-10-09 07:54:37 -0400
committerDaniel J Walsh <dwalsh@redhat.com>2018-10-12 07:08:13 -0400
commit04a537756d9b7b526759c02b5b5d68c135b210ea (patch)
tree49e8a0e7610af0b6b752d28262ef78e98e0849b3 /libpod
parentda5c89497f9d6ee5cb6e826d7db7cca5686ab4f7 (diff)
downloadpodman-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')
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/container_internal.go66
2 files changed, 71 insertions, 0 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 5997c0b66..4e17b1102 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -642,6 +642,11 @@ func (c *Container) Hostname() string {
return c.ID()[:12]
}
+// WorkingDir returns the containers working dir
+func (c *Container) WorkingDir() string {
+ return c.config.Spec.Process.Cwd
+}
+
// State Accessors
// Require locking
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