diff options
author | Matthew Heon <mheon@redhat.com> | 2020-08-31 14:06:49 -0400 |
---|---|---|
committer | Matthew Heon <mheon@redhat.com> | 2020-08-31 18:15:43 -0400 |
commit | 3875040f134de0aef01d4f360fe563f52ae7b441 (patch) | |
tree | 8dd3a3d6129cf6305b08d180ac3e6da4219e905f | |
parent | 0c076dbce5fcdc3e1994df099db77c7d51a51dec (diff) | |
download | podman-3875040f134de0aef01d4f360fe563f52ae7b441.tar.gz podman-3875040f134de0aef01d4f360fe563f52ae7b441.tar.bz2 podman-3875040f134de0aef01d4f360fe563f52ae7b441.zip |
Ensure rootless containers without a passwd can start
We want to modify /etc/passwd to add an entry for the user in
question, but at the same time we don't want to require the
container provide a /etc/passwd (a container with a single,
statically linked binary and nothing else is perfectly fine and
should be allowed, for example). We could create the passwd file
if it does not exist, but if the container doesn't provide one,
it's probably better not to make one at all. Gate changes to
/etc/passwd behind a stat() of the file in the container
returning cleanly.
Fixes #7515
Signed-off-by: Matthew Heon <mheon@redhat.com>
-rw-r--r-- | libpod/container_internal_linux.go | 11 | ||||
-rw-r--r-- | test/e2e/run_passwd_test.go | 13 |
2 files changed, 24 insertions, 0 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 31dbee572..c61c1a325 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1584,6 +1584,17 @@ func (c *Container) generatePasswd() (string, error) { if _, err := os.Stat(passwdPath); err == nil { return passwdPath, nil } + // Check if container has a /etc/passwd - if it doesn't do nothing. + passwdPath, err := securejoin.SecureJoin(c.state.Mountpoint, "/etc/passwd") + if err != nil { + return "", errors.Wrapf(err, "error creating path to container %s /etc/passwd", c.ID()) + } + if _, err := os.Stat(passwdPath); err != nil { + if os.IsNotExist(err) { + return "", nil + } + return "", errors.Wrapf(err, "unable to access container %s /etc/passwd", c.ID()) + } pwd := "" if c.config.User != "" { entry, err := c.generateUserPasswdEntry() diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go index 8dea7d39b..c48876dee 100644 --- a/test/e2e/run_passwd_test.go +++ b/test/e2e/run_passwd_test.go @@ -58,4 +58,17 @@ var _ = Describe("Podman run passwd", func() { Expect(session.ExitCode()).To(Equal(0)) Expect(session.LineInOutputContains("passwd")).To(BeTrue()) }) + + It("podman can run container without /etc/passwd", func() { + SkipIfRemote() + dockerfile := `FROM alpine +RUN rm -f /etc/passwd /etc/shadow /etc/group +USER 1000` + imgName := "testimg" + podmanTest.BuildImage(dockerfile, imgName, "false") + session := podmanTest.Podman([]string{"run", "--rm", imgName, "ls", "/etc/"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Not(ContainSubstring("passwd"))) + }) }) |