overlay: scope ID map contiguity check to mountProgram

The contiguity of ID mappings is a requirement for fuse-overlayfs, do
not impose it for the native kernel driver.

Closes: https://github.com/containers/storage/issues/2345
Closes: https://issues.redhat.com/browse/RHEL-94967

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2025-06-06 10:42:56 +02:00
parent 6498599587
commit ffb4f1504b
No known key found for this signature in database
GPG Key ID: 67E38F7A8BA21772
2 changed files with 48 additions and 6 deletions

View File

@ -2555,16 +2555,18 @@ func (d *Driver) supportsIDmappedMounts() bool {
// SupportsShifting tells whether the driver support shifting of the UIDs/GIDs to the provided mapping in an userNS
func (d *Driver) SupportsShifting(uidmap, gidmap []idtools.IDMap) bool {
if !idtools.IsContiguous(uidmap) {
return false
}
if !idtools.IsContiguous(gidmap) {
return false
}
if os.Getenv("_CONTAINERS_OVERLAY_DISABLE_IDMAP") == "yes" {
return false
}
if d.options.mountProgram != "" {
// fuse-overlayfs supports only contiguous mappings, since it performs the mapping on the
// upper layer too, to avoid https://github.com/containers/podman/issues/10272
if !idtools.IsContiguous(uidmap) {
return false
}
if !idtools.IsContiguous(gidmap) {
return false
}
return true
}
return d.supportsIDmappedMounts()

View File

@ -9,6 +9,7 @@ import (
graphdriver "github.com/containers/storage/drivers"
"github.com/containers/storage/drivers/graphtest"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/reexec"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -52,6 +53,45 @@ func TestContainersOverlayXattr(t *testing.T) {
assert.Equal(t, 0o555&os.ModePerm, fi.Mode()&os.ModePerm, root)
}
func TestSupportsShifting(t *testing.T) {
contiguousMap := []idtools.IDMap{
{
ContainerID: 0,
HostID: 1000,
Size: 65536,
},
}
nonContiguousMap := []idtools.IDMap{
{
ContainerID: 0,
HostID: 0,
Size: 1,
},
{
ContainerID: 2,
HostID: 2,
Size: 1,
},
}
t.Run("no mount program", func(t *testing.T) {
driver := graphtest.GetDriver(t, driverName)
supported := driver.SupportsShifting(nil, nil)
assert.Equal(t, supported, driver.SupportsShifting(contiguousMap, contiguousMap), "contiguous map with no mount program")
assert.Equal(t, supported, driver.SupportsShifting(nonContiguousMap, nonContiguousMap), "non-contiguous map with no mount program")
})
t.Run("with mount program", func(t *testing.T) {
driver := graphtest.GetDriver(t, driverName, "mount_program=/usr/bin/true")
assert.True(t, driver.SupportsShifting(nil, nil), "nil map with mount program")
assert.True(t, driver.SupportsShifting(contiguousMap, contiguousMap), "contiguous map with mount program")
// If a mount program is specified, SupportsShifting must return false
assert.False(t, driver.SupportsShifting(nonContiguousMap, nonContiguousMap), "non-contiguous map with mount program")
})
}
// This avoids creating a new driver for each test if all tests are run
// Make sure to put new tests between TestOverlaySetup and TestOverlayTeardown
func TestOverlaySetup(t *testing.T) {