From b59918e5367be19d63bb2d2582dd4b93649bf4f8 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 25 Jul 2024 01:11:19 +0200 Subject: [PATCH 1/2] libpod: force rootfs for OCI path with idmap when a --rootfs is specified with idmap, always use the specified rootfs since we need a new mount on top of the original directory. Signed-off-by: Giuseppe Scrivano --- libpod/container_internal.go | 2 +- libpod/oci_conmon_common.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 46cd413459..ac96a43f1d 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -2374,7 +2374,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s // the container's mountpoint directly from the storage. // Otherwise, it returns an intermediate mountpoint that is accessible to anyone. func (c *Container) getRootPathForOCI() (string, error) { - if hasCurrentUserMapped(c) { + if hasCurrentUserMapped(c) || c.config.RootfsMapping != nil { return c.state.Mountpoint, nil } return c.getIntermediateMountpointUser() diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go index c32fba46e2..ee6fbf4a37 100644 --- a/libpod/oci_conmon_common.go +++ b/libpod/oci_conmon_common.go @@ -183,7 +183,7 @@ func hasCurrentUserMapped(ctr *Container) bool { // CreateContainer creates a container. func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) (int64, error) { - if !hasCurrentUserMapped(ctr) { + if !hasCurrentUserMapped(ctr) || ctr.config.RootfsMapping != nil { // if we are running a non privileged container, be sure to umount some kernel paths so they are not // bind mounted inside the container at all. hideFiles := !ctr.config.Privileged && !rootless.IsRootless() From 7bb3b83c17fb9412ad33ad3be3810bebed8c3f03 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Wed, 24 Jul 2024 05:51:29 -0600 Subject: [PATCH 2/2] CI: enable root user namespaces Signed-off-by: Ed Santiago --- contrib/cirrus/setup_environment.sh | 7 +++++++ test/e2e/pod_create_test.go | 4 ++-- test/e2e/run_userns_test.go | 4 ++-- test/system/030-run.bats | 30 +++++++++++++++++------------ 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 420819ffdd..9390ec44c2 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -285,6 +285,13 @@ case "$PRIV_NAME" in *) die_unknown PRIV_NAME esac +# Root user namespace +for which in uid gid;do + if ! grep -qE '^containers:' /etc/sub$which; then + echo 'containers:10000000:1048576' >>/etc/sub$which + fi +done + # FIXME! experimental workaround for #16973, the "lookup cdn03.quay.io" flake. # # If you are reading this on or after April 2023: diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index c5d7ff6bb6..af7545fdda 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -797,7 +797,7 @@ ENTRYPOINT ["sleep","99999"] session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) output := session.OutputToString() - Expect(output).To(MatchRegexp("\\s0\\s0\\s1")) + Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`)) podName = "testPod-1" podCreate = podmanTest.Podman([]string{"pod", "create", "--userns=auto:size=8192,uidmapping=0:0:1", "--name", podName}) @@ -834,7 +834,7 @@ ENTRYPOINT ["sleep","99999"] session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) output := session.OutputToString() - Expect(output).To(MatchRegexp("\\s0\\s0\\s1")) + Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`)) podName = "testPod-1" podCreate = podmanTest.Podman([]string{"pod", "create", "--userns=auto:size=8192,gidmapping=0:0:1", "--name", podName}) diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index ffb0ef11d8..a5940524b9 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -282,7 +282,7 @@ var _ = Describe("Podman UserNS support", func() { session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) output := session.OutputToString() - Expect(output).To(MatchRegexp("\\s0\\s0\\s1")) + Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`)) session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,uidmapping=0:0:1", "alpine", "cat", "/proc/self/uid_map"}) session.WaitWithDefaultTimeout() @@ -311,7 +311,7 @@ var _ = Describe("Podman UserNS support", func() { session.WaitWithDefaultTimeout() Expect(session).Should(ExitCleanly()) output := session.OutputToString() - Expect(output).To(MatchRegexp("\\s0\\s0\\s1")) + Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`)) session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,gidmapping=0:0:1", "alpine", "cat", "/proc/self/gid_map"}) session.WaitWithDefaultTimeout() diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 4080a15792..6f56857219 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -1239,38 +1239,44 @@ EOF grep -E -q "^containers:" /etc/subuid || skip "no IDs allocated for user 'containers'" - # check if the underlying file system supports idmapped mounts - check_dir=$PODMAN_TMPDIR/idmap-check - mkdir $check_dir - run_podman '?' run --rm --uidmap=0:1000:10000 --rootfs $check_dir:idmap true - if [[ "$output" == *"failed to create idmapped mount: invalid argument"* ]]; then - skip "idmapped mounts not supported" - fi + # the TMPDIR must be accessible by different users as the following tests use different mappings + chmod 755 $PODMAN_TMPDIR run_podman image mount $IMAGE src="$output" # we cannot use idmap on top of overlay, so we need a copy romount=$PODMAN_TMPDIR/rootfs - cp -ar "$src" "$romount" + cp -a "$src" "$romount" run_podman image unmount $IMAGE - run_podman run --rm --uidmap=0:1000:10000 --rootfs $romount:idmap stat -c %u:%g /bin + # check if the underlying file system supports idmapped mounts + run_podman '?' run --security-opt label=disable --rm --uidmap=0:1000:10000 --rootfs $romount:idmap true + if [[ $status -ne 0 ]]; then + if [[ "$output" =~ "failed to create idmapped mount: invalid argument" ]]; then + skip "idmapped mounts not supported" + fi + # Any other error is fatal + die "Cannot create idmap mount: $output" + fi + + run_podman run --security-opt label=disable --rm --uidmap=0:1000:10000 --rootfs $romount:idmap stat -c %u:%g /bin is "$output" "0:0" - run_podman run --uidmap=0:1000:10000 --rm --rootfs "$romount:idmap=uids=0-1001-10000;gids=0-1002-10000" stat -c %u:%g /bin + run_podman run --security-opt label=disable --uidmap=0:1000:10000 --rm --rootfs "$romount:idmap=uids=0-1001-10000;gids=0-1002-10000" stat -c %u:%g /bin is "$output" "1:2" touch $romount/testfile chown 2000:2000 $romount/testfile - run_podman run --uidmap=0:1000:200 --rm --rootfs "$romount:idmap=uids=@2000-1-1;gids=@2000-1-1" stat -c %u:%g /testfile + run_podman run --security-opt label=disable --uidmap=0:1000:200 --rm --rootfs "$romount:idmap=uids=@2000-1-1;gids=@2000-1-1" stat -c %u:%g /testfile is "$output" "1:1" myvolume=my-volume-$(safename) run_podman volume create $myvolume mkdir $romount/volume - run_podman run --rm --uidmap=0:1000:10000 -v volume:/volume:idmap --rootfs $romount stat -c %u:%g /volume + chown 1000:1000 $romount/volume + run_podman run --security-opt label=disable --rm --uidmap=0:1000:10000 -v $myvolume:/volume:idmap --rootfs $romount stat -c %u:%g /volume is "$output" "0:0" run_podman volume rm $myvolume