Skip to content

Commit

Permalink
added fix for file-ownership in FUSE-mounted images + e2e test of fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Omer Preminger committed Jun 7, 2023
1 parent eb76f1a commit 1656ef9
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 20 deletions.
23 changes: 12 additions & 11 deletions e2e/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2602,16 +2602,17 @@ func E2ETests(env e2e.TestEnv) testhelper.Tests {
//
// OCI Runtime Mode
//
"ociRun": c.actionOciRun, // singularity run --oci
"ociExec": c.actionOciExec, // singularity exec --oci
"ociShell": c.actionOciShell, // singularity shell --oci
"ociSTDPIPE": c.ociSTDPipe, // stdin/stdout pipe --oci
"ociNetwork": c.actionOciNetwork, // singularity exec --oci --net
"ociBinds": c.actionOciBinds, // singularity exec --oci --bind / --mount
"ociCdi": c.actionOciCdi, // singularity exec --oci --cdi
"ociIDMaps": c.actionOciIDMaps, // check uid/gid mapping on host for --oci as user / --fakeroot
"ociCompat": np(c.actionOciCompat), // --oci equivalence to native mode --compat
"ociOverlay": (c.actionOciOverlay), // --overlay in OCI mode
"ociOverlayTeardown": np(c.actionOciOverlayTeardown), // proper overlay unmounting in OCI mode
"ociRun": c.actionOciRun, // singularity run --oci
"ociExec": c.actionOciExec, // singularity exec --oci
"ociShell": c.actionOciShell, // singularity shell --oci
"ociSTDPIPE": c.ociSTDPipe, // stdin/stdout pipe --oci
"ociNetwork": c.actionOciNetwork, // singularity exec --oci --net
"ociBinds": c.actionOciBinds, // singularity exec --oci --bind / --mount
"ociCdi": c.actionOciCdi, // singularity exec --oci --cdi
"ociIDMaps": c.actionOciIDMaps, // check uid/gid mapping on host for --oci as user / --fakeroot
"ociCompat": np(c.actionOciCompat), // --oci equivalence to native mode --compat
"ociOverlay": (c.actionOciOverlay), // --overlay in OCI mode
"ociOverlayExtfsPerms": (c.actionOciOverlayExtfsPerms), // permissions in writable extfs overlays mounted with FUSE in OCI mode
"ociOverlayTeardown": np(c.actionOciOverlayTeardown), // proper overlay unmounting in OCI mode
}
}
83 changes: 76 additions & 7 deletions e2e/actions/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
cdispecs "github.com/container-orchestrated-devices/container-device-interface/specs-go"
"github.com/sylabs/singularity/e2e/internal/e2e"
"github.com/sylabs/singularity/internal/pkg/test/tool/dirs"
"github.com/sylabs/singularity/internal/pkg/test/tool/require"
"github.com/sylabs/singularity/internal/pkg/util/fs"
"gotest.tools/v3/assert"
)
Expand Down Expand Up @@ -1331,6 +1332,16 @@ func (c actionTests) actionOciOverlay(t *testing.T) {
}
}

func haveAllCommands(t *testing.T, cmds []string) bool {
for _, c := range cmds {
if _, err := exec.LookPath(c); err != nil {
return false
}
}

return true
}

// actionOciOverlayTeardown checks that OCI-mode overlays are correctly
// unmounted even in root mode (i.e., when user namespaces are not involved).
func (c actionTests) actionOciOverlayTeardown(t *testing.T) {
Expand Down Expand Up @@ -1387,21 +1398,79 @@ func countLines(path string) (int, error) {
return lines, nil
}

func haveAllCommands(t *testing.T, cmds []string) bool {
for _, c := range cmds {
if _, err := exec.LookPath(c); err != nil {
return false
// Check that write permissions are indeed available for writable FUSE-mounted
// extfs image overlays.
func (c actionTests) actionOciOverlayExtfsPerms(t *testing.T) {
require.Command(t, "fuse2fs")
require.Command(t, "fuse-overlayfs")
require.Command(t, "fusermount")

for _, profile := range e2e.OCIProfiles {
// First, create a writable extfs overlay with `singularity overlay create`.
tmpDir, cleanup := e2e.MakeTempDir(t, c.env.TestDir, "oci_overlay_extfs_perms-", "")
t.Cleanup(func() {
if !t.Failed() {
cleanup(t)
}
})

imgPath := filepath.Join(tmpDir, "extfs-perms-test.img")

c.env.RunSingularity(
t,
e2e.WithProfile(e2e.UserProfile),
e2e.WithCommand("overlay"),
e2e.WithArgs("create", "--size", "64", imgPath),
e2e.ExpectExit(0),
)

// Now test whether we can write to, and subsequently read from, the image
// we created.
e2e.EnsureOCIArchive(t, c.env)
imageRef := "oci-archive:" + c.env.OCIArchivePath

tests := []struct {
name string
args []string
exitCode int
wantOutputs []e2e.SingularityCmdResultOp
}{
{
name: "FirstWrite",
args: []string{"--overlay", imgPath, imageRef, "sh", "-c", "echo my_test_string > /my_test_file"},
exitCode: 0,
},
{
name: "ThenRead",
args: []string{"--overlay", imgPath, imageRef, "cat", "/my_test_file"},
exitCode: 0,
wantOutputs: []e2e.SingularityCmdResultOp{
e2e.ExpectOutput(e2e.ExactMatch, "my_test_string"),
},
},
}
t.Run(profile.String(), func(t *testing.T) {
for _, tt := range tests {
c.env.RunSingularity(
t,
e2e.AsSubtest(tt.name),
e2e.WithProfile(profile),
e2e.WithCommand("exec"),
e2e.WithArgs(tt.args...),
e2e.ExpectExit(
tt.exitCode,
tt.wantOutputs...,
),
)
}
})
}

return true
}

// Make sure --workdir and --scratch work together nicely even when workdir is a
// relative path. Test needs to be run in non-parallel mode, because it changes
// the current working directory of the host.
func (c actionTests) ociRelWorkdirScratch(t *testing.T) {
e2e.EnsureOCIArchive(t, c.env)
imageRef := "oci-archive:" + c.env.OCIArchivePath

testdir, cleanup := e2e.MakeTempDir(t, c.env.TestDir, "persistent-overlay-", "")
Expand Down
4 changes: 4 additions & 0 deletions e2e/docker/regressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"testing"

"github.com/sylabs/singularity/e2e/internal/e2e"
"github.com/sylabs/singularity/internal/pkg/test/tool/dirs"
"github.com/sylabs/singularity/internal/pkg/test/tool/require"
)

Expand Down Expand Up @@ -344,6 +345,9 @@ func (c ctx) issue1670(t *testing.T) {
}
})

dirs.MkdirOrFatal(t, filepath.Join(tmpDir, "upper"), 0o777)
dirs.MkdirOrFatal(t, filepath.Join(tmpDir, "work"), 0o777)

c.env.RunSingularity(
t,
e2e.AsSubtest(profile.String()),
Expand Down
9 changes: 7 additions & 2 deletions internal/pkg/util/fs/overlay/overlay_item_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,13 @@ func (i *Item) mountWithFuse(fuseMountTool string, additionalArgs ...string) err
}
}()

args := make([]string, 0, len(additionalArgs)+2)
args = append(args, additionalArgs...)
args := make([]string, 0, len(additionalArgs)+4)

// TODO: Think through what makes sense for file ownership in FUSE-mounted
// images, vis a vis id-mappings and user-namespaces.
args = append(args, "-o")
args = append(args, "uid=0,gid=0")

args = append(args, i.SourcePath)
args = append(args, fuseMountDir)
sylog.Debugf("Executing FUSE mount command: %s %s", fuseMountCmd, strings.Join(args, " "))
Expand Down

0 comments on commit 1656ef9

Please sign in to comment.