diff --git a/internal/pkg/util/fs/fuse/fuse_mount_linux.go b/internal/pkg/util/fs/fuse/fuse_mount_linux.go index a9ccb32b4b..7053a1f59b 100644 --- a/internal/pkg/util/fs/fuse/fuse_mount_linux.go +++ b/internal/pkg/util/fs/fuse/fuse_mount_linux.go @@ -24,6 +24,12 @@ type ImageMount struct { // values in pkg/image) Type int + // UID is the value to pass to the uid option when mounting + UID int + + // GID is the value to pass to the gid option when mounting + GID int + // Readonly represents whether this is a Readonly overlay Readonly bool @@ -147,10 +153,6 @@ func (i *ImageMount) generateCmdArgs() ([]string, error) { } func (i ImageMount) generateMountOpts() ([]string, error) { - // TODO: Think through what makes sense for file ownership in FUSE-mounted - // images, vis a vis id-mappings and user-namespaces. - opts := []string{"uid=0", "gid=0"} - // Create a map of the extra mount options that have been requested, so we // can catch attempts to overwrite builtin struct fields. extraOptsMap := lo.SliceToMap(i.ExtraOpts, func(s string) (string, *string) { @@ -162,6 +164,18 @@ func (i ImageMount) generateMountOpts() ([]string, error) { return strings.ToLower(splitted[0]), &splitted[1] }) + opts := []string{} + + if err := checkProhibitedOpt(extraOptsMap, "uid"); err != nil { + return opts, err + } + opts = append(opts, fmt.Sprintf("uid=%d", i.UID)) + + if err := checkProhibitedOpt(extraOptsMap, "gid"); err != nil { + return opts, err + } + opts = append(opts, fmt.Sprintf("gid=%d", i.GID)) + if err := checkProhibitedOpt(extraOptsMap, "ro"); err != nil { return opts, err } diff --git a/internal/pkg/util/fs/fuse/fuse_mount_linux_test.go b/internal/pkg/util/fs/fuse/fuse_mount_linux_test.go index 2d1cffd6b3..8a3153ea5d 100644 --- a/internal/pkg/util/fs/fuse/fuse_mount_linux_test.go +++ b/internal/pkg/util/fs/fuse/fuse_mount_linux_test.go @@ -15,12 +15,26 @@ import ( var squashfsImgPath = filepath.Join("..", "..", "..", "..", "..", "test", "images", "squashfs-for-overlay.img") +var optsToTest = []string{ + "uid=0", + "gid=0", + "uid=23", + "gid=67", + "uid=2345", + "gid=6789", + "rw", + "ro", + "dev", + "nodev", + "suid", + "nosuid", + "allow_other", +} + func TestExtraOptOverrides(t *testing.T) { - testOneOverride(t, "rw") - testOneOverride(t, "ro") - testOneOverride(t, "dev") - testOneOverride(t, "suid") - testOneOverride(t, "allow_other") + for _, opt := range optsToTest { + testOneOverride(t, opt) + } } func testOneOverride(t *testing.T, s string) { @@ -63,7 +77,7 @@ func TestAllOverridesAtOnce(t *testing.T) { t.Fatalf("Baseline unmount of %q failed: %v", m.SourcePath, err) } - m.ExtraOpts = []string{"suid", "allow_other", "rw", "dev"} + m.ExtraOpts = optsToTest[:] if err := m.Mount(ctx); err == nil { t.Errorf("Failed to block mount options (%q).", m.ExtraOpts) diff --git a/internal/pkg/util/fs/squashfs/squashfs.go b/internal/pkg/util/fs/squashfs/squashfs.go index 82607e18ee..4b0124baf4 100644 --- a/internal/pkg/util/fs/squashfs/squashfs.go +++ b/internal/pkg/util/fs/squashfs/squashfs.go @@ -18,12 +18,12 @@ import ( func FUSEMount(ctx context.Context, offset uint64, path, mountPath string) (*fuse.ImageMount, error) { im := fuse.ImageMount{ Type: image.SQUASHFS, + UID: os.Getuid(), + GID: os.Getgid(), Readonly: true, SourcePath: filepath.Clean(path), ExtraOpts: []string{ fmt.Sprintf("offset=%d", offset), - fmt.Sprintf("uid=%d", os.Getuid()), - fmt.Sprintf("gid=%d", os.Getgid()), }, } im.SetMountPoint(filepath.Clean(mountPath))