Make changes to /etc/passwd on disk for non-read only

Bind-mounting /etc/passwd into the container is problematic
becuase of how system utilities like `useradd` work. They want
to make a copy and then rename to try to prevent breakage; this
is, unfortunately, impossible when the file they want to rename
is a bind mount. The current behavior is fine for read-only
containers, though, because we expect useradd to fail in those
cases.

Instead of bind-mounting, we can edit /etc/passwd in the
container's rootfs. This is kind of gross, because the change
will show up in `podman diff` and similar tools, and will be
included in images made by `podman commit`. However, it's a lot
better than breaking important system tools.

Fixes #6953

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
Matthew Heon
2020-07-15 15:25:12 -04:00
committed by Matthew Heon
parent 9051546c4d
commit bae6853906
3 changed files with 72 additions and 9 deletions

View File

@ -35,27 +35,27 @@ var _ = Describe("Podman run passwd", func() {
})
It("podman run no user specified ", func() {
session := podmanTest.Podman([]string{"run", BB, "mount"})
session := podmanTest.Podman([]string{"run", "--read-only", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOutputContains("passwd")).To(BeFalse())
})
It("podman run user specified in container", func() {
session := podmanTest.Podman([]string{"run", "-u", "bin", BB, "mount"})
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "bin", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOutputContains("passwd")).To(BeFalse())
})
It("podman run UID specified in container", func() {
session := podmanTest.Podman([]string{"run", "-u", "2:1", BB, "mount"})
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "2:1", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOutputContains("passwd")).To(BeFalse())
})
It("podman run UID not specified in container", func() {
session := podmanTest.Podman([]string{"run", "-u", "20001:1", BB, "mount"})
session := podmanTest.Podman([]string{"run", "--read-only", "-u", "20001:1", BB, "mount"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOutputContains("passwd")).To(BeTrue())