From 85024a9ba7ade20271cd8e1b121c5c835fe083c3 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 7 Apr 2025 11:20:04 +0200 Subject: [PATCH] libpod: --user works with --hostuser entries create the /etc/passwd and /etc/group files before any user/group lookup so that the entries added dynamically are found by --user. As a side effect, do not automatically create the group with same value as the uid when not specified, since it is expected to run with gid=0. Closes: https://github.com/containers/podman/issues/25805 Signed-off-by: Giuseppe Scrivano --- libpod/container_internal_common.go | 22 +++++++++------------- libpod/container_internal_linux_test.go | 6 +++--- test/e2e/run_passwd_test.go | 7 ------- test/system/030-run.bats | 11 +++++++++++ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index d9b7e33da0..f48afcab7a 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -195,15 +195,15 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc cleanupFunc() } }() + + if err := c.makeBindMounts(); err != nil { + return nil, nil, err + } + overrides := c.getUserOverrides() execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, overrides) if err != nil { - if slices.Contains(c.config.HostUsers, c.config.User) { - execUser, err = lookupHostUser(c.config.User) - } - if err != nil { - return nil, nil, err - } + return nil, nil, err } // NewFromSpec() is deprecated according to its comment @@ -236,10 +236,6 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc g.SetProcessApparmorProfile(updatedProfile) } - if err := c.makeBindMounts(); err != nil { - return nil, nil, err - } - if err := c.mountNotifySocket(g); err != nil { return nil, nil, err } @@ -2434,7 +2430,7 @@ func (c *Container) generateGroupEntry() (string, error) { // Things we *can't* handle: adding the user we added in // generatePasswdEntry to any *existing* groups. - addedGID := 0 + addedGID := -1 if c.config.AddCurrentUserPasswdEntry { entry, gid, err := c.generateCurrentUserGroupEntry() if err != nil { @@ -2503,7 +2499,7 @@ func (c *Container) generateUserGroupEntry(addedGID int) (string, error) { } splitUser := strings.SplitN(c.config.User, ":", 2) - group := splitUser[0] + group := "0" if len(splitUser) > 1 { group = splitUser[1] } @@ -2513,7 +2509,7 @@ func (c *Container) generateUserGroupEntry(addedGID int) (string, error) { return "", nil //nolint: nilerr } - if addedGID != 0 && addedGID == int(gid) { + if addedGID != -1 && addedGID == int(gid) { return "", nil } diff --git a/libpod/container_internal_linux_test.go b/libpod/container_internal_linux_test.go index 4deb513b8a..0ab62dd994 100644 --- a/libpod/container_internal_linux_test.go +++ b/libpod/container_internal_linux_test.go @@ -47,16 +47,16 @@ func TestGenerateUserGroupEntry(t *testing.T) { Mountpoint: "/does/not/exist/tmp/", }, } - group, err := c.generateUserGroupEntry(0) + group, err := c.generateUserGroupEntry(-1) if err != nil { t.Fatal(err) } assert.Equal(t, group, "456789:x:456789:123456\n") c.config.User = "567890" - group, err = c.generateUserGroupEntry(0) + group, err = c.generateUserGroupEntry(-1) if err != nil { t.Fatal(err) } - assert.Equal(t, group, "567890:x:567890:567890\n") + assert.Equal(t, group, "0:x:0:567890\n") } diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go index 8381ca1bdb..7c064bebd8 100644 --- a/test/e2e/run_passwd_test.go +++ b/test/e2e/run_passwd_test.go @@ -90,13 +90,6 @@ USER 1000`, ALPINE) Expect(session.OutputToString()).To(ContainSubstring("/etc/group")) }) - It("podman run numeric user not specified in container modifies group", func() { - session := podmanTest.Podman([]string{"run", "--read-only", "-u", "20001", BB, "mount"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(ExitCleanly()) - Expect(session.OutputToString()).To(ContainSubstring("/etc/group")) - }) - It("podman run numeric group from image and no group file", func() { dockerfile := fmt.Sprintf(`FROM %s RUN rm -f /etc/passwd /etc/shadow /etc/group diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 348e1e962b..9853abc494 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -906,6 +906,17 @@ EOF fi user=$(id -u) + + userspec=$(id -un):$(id -g) + run_podman run --hostuser=$user --user $userspec --rm $IMAGE sh -c 'echo $(id -un):$(id -g)' + is "$output" "$userspec" + + run_podman run --hostuser=$user --user $userspec --group-entry="$(id -gn):x:$(id -g):" --rm $IMAGE sh -c 'echo $(id -un):$(id -gn)' + is "$output" "$(id -un):$(id -gn)" + + run_podman 126 run --hostuser=$user --user "$(id -un):$(id -gn)" --rm $IMAGE sh -c 'echo $(id -un):$(id -gn)' + is "$output" "Error:.* no matching entries in group file" + run_podman run --hostuser=$user --rm $IMAGE grep $user /etc/passwd run_podman run --hostuser=$user --user $user --rm $IMAGE grep $user /etc/passwd user=bogus