Skip to content

Commit 76d1690

Browse files
Merge pull request #24591 from giuseppe/backport-5.2-idmap
[5.2-rhel] libpod: fix volume copyup with idmap | convert owner IDs only with :idmap
2 parents e40738b + b00c7f2 commit 76d1690

File tree

7 files changed

+53
-30
lines changed

7 files changed

+53
-30
lines changed

contrib/cirrus/setup_environment.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ case "$PRIV_NAME" in
285285
*) die_unknown PRIV_NAME
286286
esac
287287

288+
# Root user namespace
289+
for which in uid gid;do
290+
if ! grep -qE '^containers:' /etc/sub$which; then
291+
echo 'containers:10000000:1048576' >>/etc/sub$which
292+
fi
293+
done
294+
288295
# FIXME! experimental workaround for #16973, the "lookup cdn03.quay.io" flake.
289296
#
290297
# If you are reading this on or after April 2023:

libpod/container_internal.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,11 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
19241924
getOptions := copier.GetOptions{
19251925
KeepDirectoryNames: false,
19261926
}
1927+
// If the volume is idmapped, we need to "undo" the idmapping
1928+
if slices.Contains(v.Options, "idmap") {
1929+
getOptions.UIDMap = c.config.IDMappings.UIDMap
1930+
getOptions.GIDMap = c.config.IDMappings.GIDMap
1931+
}
19271932
errChan <- copier.Get(srcDir, "", getOptions, []string{"/."}, writer)
19281933
}()
19291934

libpod/container_internal_common.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,8 +2900,10 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
29002900
uid := int(c.config.Spec.Process.User.UID)
29012901
gid := int(c.config.Spec.Process.User.GID)
29022902

2903+
idmapped := hasIdmapOption(v.Options)
2904+
29032905
// if the volume is mounted with "idmap", leave the IDs in from the current environment.
2904-
if c.config.IDMappings.UIDMap != nil && !hasIdmapOption(v.Options) {
2906+
if c.config.IDMappings.UIDMap != nil && !idmapped {
29052907
p := idtools.IDPair{
29062908
UID: uid,
29072909
GID: gid,
@@ -2947,7 +2949,8 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
29472949
if stat, ok := st.Sys().(*syscall.Stat_t); ok {
29482950
uid, gid := int(stat.Uid), int(stat.Gid)
29492951

2950-
if c.config.IDMappings.UIDMap != nil {
2952+
// If the volume is idmapped then undo the conversion to obtain the desired UID/GID in the container
2953+
if c.config.IDMappings.UIDMap != nil && idmapped {
29512954
p := idtools.IDPair{
29522955
UID: uid,
29532956
GID: gid,

libpod/runtime_ctr.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -513,16 +513,11 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
513513
volOptions = append(volOptions, withSetAnon())
514514
}
515515

516-
needsChown := true
517-
518516
// If volume-opts are set, parse and add driver opts.
519517
if len(vol.Options) > 0 {
520518
isDriverOpts := false
521519
driverOpts := make(map[string]string)
522520
for _, opts := range vol.Options {
523-
if opts == "idmap" {
524-
needsChown = false
525-
}
526521
if strings.HasPrefix(opts, "volume-opt") {
527522
isDriverOpts = true
528523
driverOptKey, driverOptValue, err := util.ParseDriverOpts(opts)
@@ -538,11 +533,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
538533
}
539534
}
540535

541-
if needsChown {
542-
volOptions = append(volOptions, WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID()))
543-
} else {
544-
volOptions = append(volOptions, WithVolumeNoChown())
545-
}
536+
volOptions = append(volOptions, WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID()))
546537

547538
_, err = r.newVolume(ctx, false, volOptions...)
548539
if err != nil {

test/e2e/pod_create_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ ENTRYPOINT ["sleep","99999"]
799799
session.WaitWithDefaultTimeout()
800800
Expect(session).Should(ExitCleanly())
801801
output := session.OutputToString()
802-
Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
802+
Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`))
803803

804804
podName = "testPod-1"
805805
podCreate = podmanTest.Podman([]string{"pod", "create", "--userns=auto:size=8192,uidmapping=0:0:1", "--name", podName})
@@ -836,7 +836,7 @@ ENTRYPOINT ["sleep","99999"]
836836
session.WaitWithDefaultTimeout()
837837
Expect(session).Should(ExitCleanly())
838838
output := session.OutputToString()
839-
Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
839+
Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`))
840840

841841
podName = "testPod-1"
842842
podCreate = podmanTest.Podman([]string{"pod", "create", "--userns=auto:size=8192,gidmapping=0:0:1", "--name", podName})

test/e2e/run_userns_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ var _ = Describe("Podman UserNS support", func() {
284284
session.WaitWithDefaultTimeout()
285285
Expect(session).Should(ExitCleanly())
286286
output := session.OutputToString()
287-
Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
287+
Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`))
288288

289289
session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,uidmapping=0:0:1", "alpine", "cat", "/proc/self/uid_map"})
290290
session.WaitWithDefaultTimeout()
@@ -313,7 +313,7 @@ var _ = Describe("Podman UserNS support", func() {
313313
session.WaitWithDefaultTimeout()
314314
Expect(session).Should(ExitCleanly())
315315
output := session.OutputToString()
316-
Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
316+
Expect(output).To(MatchRegexp(`(^|\s)0\s+0\s+1(\s|$)`))
317317

318318
session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,gidmapping=0:0:1", "alpine", "cat", "/proc/self/gid_map"})
319319
session.WaitWithDefaultTimeout()

test/system/030-run.bats

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,46 +1253,63 @@ EOF
12531253
fi
12541254
}
12551255

1256-
@test "podman run - rootfs with idmapped mounts" {
1256+
@test "podman run - idmapped mounts" {
12571257
skip_if_rootless "idmapped mounts work only with root for now"
12581258

12591259
skip_if_remote "userns=auto is set on the server"
12601260

12611261
grep -E -q "^containers:" /etc/subuid || skip "no IDs allocated for user 'containers'"
12621262

1263-
# check if the underlying file system supports idmapped mounts
1264-
check_dir=$PODMAN_TMPDIR/idmap-check
1265-
mkdir $check_dir
1266-
run_podman '?' run --rm --uidmap=0:1000:10000 --rootfs $check_dir:idmap true
1267-
if [[ "$output" == *"failed to create idmapped mount: invalid argument"* ]]; then
1268-
skip "idmapped mounts not supported"
1269-
fi
1263+
# the TMPDIR must be accessible by different users as the following tests use different mappings
1264+
chmod 755 $PODMAN_TMPDIR
12701265

12711266
run_podman image mount $IMAGE
12721267
src="$output"
12731268

12741269
# we cannot use idmap on top of overlay, so we need a copy
12751270
romount=$PODMAN_TMPDIR/rootfs
1276-
cp -ar "$src" "$romount"
1271+
cp -a "$src" "$romount"
12771272

12781273
run_podman image unmount $IMAGE
12791274

1280-
run_podman run --rm --uidmap=0:1000:10000 --rootfs $romount:idmap stat -c %u:%g /bin
1275+
# check if the underlying file system supports idmapped mounts
1276+
run_podman '?' run --security-opt label=disable --rm --uidmap=0:1000:10000 --rootfs $romount:idmap true
1277+
if [[ $status -ne 0 ]]; then
1278+
if [[ "$output" =~ "failed to create idmapped mount: invalid argument" ]]; then
1279+
skip "idmapped mounts not supported"
1280+
fi
1281+
# Any other error is fatal
1282+
die "Cannot create idmap mount: $output"
1283+
fi
1284+
1285+
run_podman run --security-opt label=disable --rm --uidmap=0:1000:10000 --rootfs $romount:idmap stat -c %u:%g /bin
12811286
is "$output" "0:0"
12821287

1283-
run_podman run --uidmap=0:1000:10000 --rm --rootfs "$romount:idmap=uids=0-1001-10000;gids=0-1002-10000" stat -c %u:%g /bin
1288+
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
12841289
is "$output" "1:2"
12851290

12861291
touch $romount/testfile
12871292
chown 2000:2000 $romount/testfile
1288-
run_podman run --uidmap=0:1000:200 --rm --rootfs "$romount:idmap=uids=@2000-1-1;gids=@2000-1-1" stat -c %u:%g /testfile
1293+
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
12891294
is "$output" "1:1"
12901295

1296+
# verify that copyup with an empty idmap volume maintains the original ownership with different mappings and --rootfs
12911297
myvolume=my-volume-$(safename)
12921298
run_podman volume create $myvolume
12931299
mkdir $romount/volume
1294-
run_podman run --rm --uidmap=0:1000:10000 -v volume:/volume:idmap --rootfs $romount stat -c %u:%g /volume
1295-
is "$output" "0:0"
1300+
chown 1000:1000 $romount/volume
1301+
for FROM in 1000 2000; do
1302+
run_podman run --security-opt label=disable --rm --uidmap=0:$FROM:10000 -v $myvolume:/volume:idmap --rootfs $romount stat -c %u:%g /volume
1303+
is "$output" "0:0"
1304+
done
1305+
run_podman volume rm $myvolume
1306+
1307+
# verify that copyup with an empty idmap volume maintains the original ownership with different mappings
1308+
myvolume=my-volume-$(safename)
1309+
for FROM in 1000 2000; do
1310+
run_podman run --rm --uidmap=0:$FROM:10000 -v $myvolume:/etc:idmap $IMAGE stat -c %u:%g /etc/passwd
1311+
is "$output" "0:0"
1312+
done
12961313
run_podman volume rm $myvolume
12971314

12981315
rm -rf $romount

0 commit comments

Comments
 (0)