diff options
-rw-r--r-- | libpod/container_internal_linux.go | 27 | ||||
-rw-r--r-- | libpod/oci_internal_linux.go | 22 | ||||
-rw-r--r-- | pkg/lookup/lookup.go | 30 | ||||
-rw-r--r-- | test/e2e/run_test.go | 6 |
4 files changed, 67 insertions, 18 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 355b9bea4..230b5b888 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -181,6 +181,30 @@ func (c *Container) cleanupNetwork() error { return nil } +func (c *Container) getUserOverrides() *lookup.Overrides { + var hasPasswdFile, hasGroupFile bool + overrides := lookup.Overrides{} + for _, m := range c.config.Spec.Mounts { + if m.Destination == "/etc/passwd" { + overrides.ContainerEtcPasswdPath = m.Source + hasPasswdFile = true + } + if m.Destination == "/etc/group" { + overrides.ContainerEtcGroupPath = m.Source + hasGroupFile = true + } + if m.Destination == "/etc" { + if !hasPasswdFile { + overrides.ContainerEtcPasswdPath = filepath.Join(m.Source, "passwd") + } + if !hasGroupFile { + overrides.ContainerEtcGroupPath = filepath.Join(m.Source, "group") + } + } + } + return &overrides +} + // Generate spec for a container // Accepts a map of the container's dependencies func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { @@ -188,7 +212,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { span.SetTag("type", "container") defer span.Finish() - execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, nil) + overrides := c.getUserOverrides() + execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, overrides) if err != nil { return nil, err } diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go index 4df1e4010..a90af32ed 100644 --- a/libpod/oci_internal_linux.go +++ b/libpod/oci_internal_linux.go @@ -200,13 +200,16 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se pspec.Cwd = cwd } + + overrides := c.getUserOverrides() + execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, overrides) + if err != nil { + return nil, err + } + // If user was set, look it up in the container to get a UID to use on // the host if user != "" { - execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, nil) - if err != nil { - return nil, err - } sgids := make([]uint32, 0, len(execUser.Sgids)) for _, sgid := range execUser.Sgids { sgids = append(sgids, uint32(sgid)) @@ -220,6 +223,17 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se pspec.User = processUser } + hasHomeSet := false + for _, s := range pspec.Env { + if strings.HasPrefix(s, "HOME=") { + hasHomeSet = true + break + } + } + if !hasHomeSet { + pspec.Env = append(pspec.Env, fmt.Sprintf("HOME=%s", execUser.Home)) + } + processJSON, err := json.Marshal(pspec) if err != nil { return nil, err diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go index 70b97144f..a249dd753 100644 --- a/pkg/lookup/lookup.go +++ b/pkg/lookup/lookup.go @@ -29,17 +29,30 @@ func GetUserGroupInfo(containerMount, containerUser string, override *Overrides) defaultExecUser *user.ExecUser err error ) - passwdPath := etcpasswd - groupPath := etcgroup if override != nil { // Check for an override /etc/passwd path if override.ContainerEtcPasswdPath != "" { - passwdPath = override.ContainerEtcPasswdPath + passwdDest = override.ContainerEtcPasswdPath } // Check for an override for /etc/group path if override.ContainerEtcGroupPath != "" { - groupPath = override.ContainerEtcGroupPath + groupDest = override.ContainerEtcGroupPath + } + } + + if passwdDest == "" { + // Make sure the /etc/passwd destination is not a symlink to something naughty + if passwdDest, err = securejoin.SecureJoin(containerMount, etcpasswd); err != nil { + logrus.Debug(err) + return nil, err + } + } + if groupDest == "" { + // Make sure the /etc/group destination is not a symlink to something naughty + if groupDest, err = securejoin.SecureJoin(containerMount, etcgroup); err != nil { + logrus.Debug(err) + return nil, err } } @@ -56,15 +69,6 @@ func GetUserGroupInfo(containerMount, containerUser string, override *Overrides) } - // Make sure the /etc/group and /etc/passwd destinations are not a symlink to something naughty - if passwdDest, err = securejoin.SecureJoin(containerMount, passwdPath); err != nil { - logrus.Debug(err) - return nil, err - } - if groupDest, err = securejoin.SecureJoin(containerMount, groupPath); err != nil { - logrus.Debug(err) - return nil, err - } return user.GetExecUserPath(containerUser, defaultExecUser, passwdDest, groupDest) } diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 55920467c..1e6f1d97d 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -200,6 +200,12 @@ var _ = Describe("Podman run", func() { match, _ := session.GrepString("/root") Expect(match).Should(BeTrue()) + session = podmanTest.Podman([]string{"run", "--rm", "--user", "2", ALPINE, "printenv", "HOME"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ = session.GrepString("/sbin") + Expect(match).Should(BeTrue()) + session = podmanTest.Podman([]string{"run", "--rm", "--env", "HOME=/foo", ALPINE, "printenv", "HOME"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) |