diff options
Diffstat (limited to 'runsc/container/container_test.go')
-rw-r--r-- | runsc/container/container_test.go | 306 |
1 files changed, 249 insertions, 57 deletions
diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 867bf8187..c1d6ca7b8 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -17,6 +17,7 @@ package container import ( "bytes" "fmt" + "io" "io/ioutil" "os" "path" @@ -31,13 +32,14 @@ import ( "github.com/cenkalti/backoff" specs "github.com/opencontainers/runtime-spec/specs-go" - "gvisor.googlesource.com/gvisor/pkg/abi/linux" - "gvisor.googlesource.com/gvisor/pkg/log" - "gvisor.googlesource.com/gvisor/pkg/sentry/control" - "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/auth" - "gvisor.googlesource.com/gvisor/runsc/boot" - "gvisor.googlesource.com/gvisor/runsc/specutils" - "gvisor.googlesource.com/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/log" + "gvisor.dev/gvisor/pkg/sentry/control" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/runsc/boot" + "gvisor.dev/gvisor/runsc/boot/platforms" + "gvisor.dev/gvisor/runsc/specutils" + "gvisor.dev/gvisor/runsc/test/testutil" ) // waitForProcessList waits for the given process list to show up in the container. @@ -211,7 +213,13 @@ func run(spec *specs.Spec, conf *boot.Config) error { defer os.RemoveAll(bundleDir) // Create, start and wait for the container. - ws, err := Run(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "", false) + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + Attached: true, + } + ws, err := Run(conf, args) if err != nil { return fmt.Errorf("running container: %v", err) } @@ -250,7 +258,7 @@ func configs(opts ...configOption) []*boot.Config { if testutil.RaceEnabled { continue } - c.Platform = boot.PlatformKVM + c.Platform = platforms.KVM case nonExclusiveFS: c.FileAccess = boot.FileAccessShared default: @@ -295,15 +303,19 @@ func TestLifecycle(t *testing.T) { }, } // Create the container. - id := testutil.UniqueContainerID() - c, err := Create(id, spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } defer c.Destroy() // Load the container from disk and check the status. - c, err = Load(rootDir, id) + c, err = Load(rootDir, args.ID) if err != nil { t.Fatalf("error loading container: %v", err) } @@ -316,7 +328,7 @@ func TestLifecycle(t *testing.T) { if err != nil { t.Fatalf("error listing containers: %v", err) } - if got, want := ids, []string{id}; !reflect.DeepEqual(got, want) { + if got, want := ids, []string{args.ID}; !reflect.DeepEqual(got, want) { t.Errorf("container list got %v, want %v", got, want) } @@ -326,7 +338,7 @@ func TestLifecycle(t *testing.T) { } // Load the container from disk and check the status. - c, err = Load(rootDir, id) + c, err = Load(rootDir, args.ID) if err != nil { t.Fatalf("error loading container: %v", err) } @@ -367,7 +379,7 @@ func TestLifecycle(t *testing.T) { wg.Wait() // Load the container from disk and check the status. - c, err = Load(rootDir, id) + c, err = Load(rootDir, args.ID) if err != nil { t.Fatalf("error loading container: %v", err) } @@ -390,7 +402,7 @@ func TestLifecycle(t *testing.T) { } // Loading the container by id should fail. - if _, err = Load(rootDir, id); err == nil { + if _, err = Load(rootDir, args.ID); err == nil { t.Errorf("expected loading destroyed container to fail, but it did not") } } @@ -398,6 +410,46 @@ func TestLifecycle(t *testing.T) { // Test the we can execute the application with different path formats. func TestExePath(t *testing.T) { + // Create two directories that will be prepended to PATH. + firstPath, err := ioutil.TempDir(testutil.TmpDir(), "first") + if err != nil { + t.Fatal(err) + } + secondPath, err := ioutil.TempDir(testutil.TmpDir(), "second") + if err != nil { + t.Fatal(err) + } + + // Create two minimal executables in the second path, two of which + // will be masked by files in first path. + for _, p := range []string{"unmasked", "masked1", "masked2"} { + path := filepath.Join(secondPath, p) + f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0777) + if err != nil { + t.Fatal(err) + } + defer f.Close() + if _, err := io.WriteString(f, "#!/bin/true\n"); err != nil { + t.Fatal(err) + } + } + + // Create a non-executable file in the first path which masks a healthy + // executable in the second. + nonExecutable := filepath.Join(firstPath, "masked1") + f2, err := os.OpenFile(nonExecutable, os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + t.Fatal(err) + } + f2.Close() + + // Create a non-regular file in the first path which masks a healthy + // executable in the second. + nonRegular := filepath.Join(firstPath, "masked2") + if err := os.Mkdir(nonRegular, 0777); err != nil { + t.Fatal(err) + } + for _, conf := range configs(overlay) { t.Logf("Running test with conf: %+v", conf) for _, test := range []struct { @@ -410,14 +462,36 @@ func TestExePath(t *testing.T) { {path: "thisfiledoesntexit", success: false}, {path: "bin/thisfiledoesntexit", success: false}, {path: "/bin/thisfiledoesntexit", success: false}, + + {path: "unmasked", success: true}, + {path: filepath.Join(firstPath, "unmasked"), success: false}, + {path: filepath.Join(secondPath, "unmasked"), success: true}, + + {path: "masked1", success: true}, + {path: filepath.Join(firstPath, "masked1"), success: false}, + {path: filepath.Join(secondPath, "masked1"), success: true}, + + {path: "masked2", success: true}, + {path: filepath.Join(firstPath, "masked2"), success: false}, + {path: filepath.Join(secondPath, "masked2"), success: true}, } { spec := testutil.NewSpecWithArgs(test.path) + spec.Process.Env = []string{ + fmt.Sprintf("PATH=%s:%s:%s", firstPath, secondPath, os.Getenv("PATH")), + } + rootDir, bundleDir, err := testutil.SetupContainer(spec, conf) if err != nil { t.Fatalf("exec: %s, error setting up container: %v", test.path, err) } - ws, err := Run(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "", false) + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + Attached: true, + } + ws, err := Run(conf, args) os.RemoveAll(rootDir) os.RemoveAll(bundleDir) @@ -450,7 +524,13 @@ func TestAppExitStatus(t *testing.T) { defer os.RemoveAll(rootDir) defer os.RemoveAll(bundleDir) - ws, err := Run(testutil.UniqueContainerID(), succSpec, conf, bundleDir, "", "", "", false) + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: succSpec, + BundleDir: bundleDir, + Attached: true, + } + ws, err := Run(conf, args) if err != nil { t.Fatalf("error running container: %v", err) } @@ -469,7 +549,13 @@ func TestAppExitStatus(t *testing.T) { defer os.RemoveAll(rootDir2) defer os.RemoveAll(bundleDir2) - ws, err = Run(testutil.UniqueContainerID(), errSpec, conf, bundleDir2, "", "", "", false) + args2 := Args{ + ID: testutil.UniqueContainerID(), + Spec: errSpec, + BundleDir: bundleDir2, + Attached: true, + } + ws, err = Run(conf, args2) if err != nil { t.Fatalf("error running container: %v", err) } @@ -494,7 +580,12 @@ func TestExec(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -526,7 +617,7 @@ func TestExec(t *testing.T) { t.Error(err) } - args := &control.ExecArgs{ + execArgs := &control.ExecArgs{ Filename: "/bin/sleep", Argv: []string{"/bin/sleep", "5"}, WorkingDirectory: "/", @@ -537,7 +628,7 @@ func TestExec(t *testing.T) { // First, start running exec (whick blocks). status := make(chan error, 1) go func() { - exitStatus, err := cont.executeSync(args) + exitStatus, err := cont.executeSync(execArgs) if err != nil { log.Debugf("error executing: %v", err) status <- err @@ -585,7 +676,12 @@ func TestKillPid(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -656,7 +752,12 @@ func TestCheckpointRestore(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -702,7 +803,12 @@ func TestCheckpointRestore(t *testing.T) { defer outputFile2.Close() // Restore into a new container. - cont2, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args2 := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont2, err := New(conf, args2) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -741,7 +847,12 @@ func TestCheckpointRestore(t *testing.T) { defer outputFile3.Close() // Restore into a new container. - cont3, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args3 := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont3, err := New(conf, args3) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -778,7 +889,7 @@ func TestUnixDomainSockets(t *testing.T) { t.Logf("Running test with conf: %+v", conf) // UDS path is limited to 108 chars for compatibility with older systems. - // Use '/tmp' (instead of testutil.TmpDir) to to ensure the size limit is + // Use '/tmp' (instead of testutil.TmpDir) to ensure the size limit is // not exceeded. Assumes '/tmp' exists in the system. dir, err := ioutil.TempDir("/tmp", "uds-test") if err != nil { @@ -820,7 +931,12 @@ func TestUnixDomainSockets(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -867,7 +983,12 @@ func TestUnixDomainSockets(t *testing.T) { defer outputFile2.Close() // Restore into a new container. - contRestore, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + argsRestore := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + contRestore, err := New(conf, argsRestore) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -921,7 +1042,12 @@ func TestPauseResume(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -949,7 +1075,7 @@ func TestPauseResume(t *testing.T) { } script := fmt.Sprintf("while [[ -f %q ]]; do sleep 0.1; done", lock.Name()) - args := &control.ExecArgs{ + execArgs := &control.ExecArgs{ Filename: "/bin/bash", Argv: []string{"bash", "-c", script}, WorkingDirectory: "/", @@ -957,7 +1083,7 @@ func TestPauseResume(t *testing.T) { } // First, start running exec. - _, err = cont.Execute(args) + _, err = cont.Execute(execArgs) if err != nil { t.Fatalf("error executing: %v", err) } @@ -1026,7 +1152,12 @@ func TestPauseResumeStatus(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1090,7 +1221,12 @@ func TestCapabilities(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1132,7 +1268,7 @@ func TestCapabilities(t *testing.T) { // Need to traverse the intermediate directory. os.Chmod(rootDir, 0755) - args := &control.ExecArgs{ + execArgs := &control.ExecArgs{ Filename: exePath, Argv: []string{exePath}, WorkingDirectory: "/", @@ -1142,16 +1278,16 @@ func TestCapabilities(t *testing.T) { } // "exe" should fail because we don't have the necessary permissions. - if _, err := cont.executeSync(args); err == nil { + if _, err := cont.executeSync(execArgs); err == nil { t.Fatalf("container executed without error, but an error was expected") } // Now we run with the capability enabled and should succeed. - args.Capabilities = &auth.TaskCapabilities{ + execArgs.Capabilities = &auth.TaskCapabilities{ EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), } // "exe" should not fail this time. - if _, err := cont.executeSync(args); err != nil { + if _, err := cont.executeSync(execArgs); err != nil { t.Fatalf("container failed to exec %v: %v", args, err) } } @@ -1232,7 +1368,12 @@ func TestReadonlyRoot(t *testing.T) { defer os.RemoveAll(bundleDir) // Create, start and wait for the container. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1300,7 +1441,12 @@ func TestUIDMap(t *testing.T) { defer os.RemoveAll(bundleDir) // Create, start and wait for the container. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1352,7 +1498,12 @@ func TestReadonlyMount(t *testing.T) { defer os.RemoveAll(bundleDir) // Create, start and wait for the container. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1396,7 +1547,12 @@ func TestAbbreviatedIDs(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - cont, err := Create(cid, spec, conf, bundleDir, "", "", "") + args := Args{ + ID: cid, + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1441,7 +1597,12 @@ func TestGoferExits(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and start the container. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1520,7 +1681,14 @@ func TestUserLog(t *testing.T) { userLog := filepath.Join(dir, "user.log") // Create, start and wait for the container. - ws, err := Run(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", userLog, false) + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + UserLog: userLog, + Attached: true, + } + ws, err := Run(conf, args) if err != nil { t.Fatalf("error running container: %v", err) } @@ -1554,7 +1722,12 @@ func TestWaitOnExitedSandbox(t *testing.T) { defer os.RemoveAll(bundleDir) // Create and Start the container. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1597,7 +1770,12 @@ func TestDestroyNotStarted(t *testing.T) { defer os.RemoveAll(bundleDir) // Create the container and check that it can be destroyed. - c, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } @@ -1619,15 +1797,19 @@ func TestDestroyStarting(t *testing.T) { defer os.RemoveAll(bundleDir) // Create the container and check that it can be destroyed. - id := testutil.UniqueContainerID() - c, err := Create(id, spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + c, err := New(conf, args) if err != nil { t.Fatalf("error creating container: %v", err) } // Container is not thread safe, so load another instance to run in // concurrently. - startCont, err := Load(rootDir, id) + startCont, err := Load(rootDir, args.ID) if err != nil { t.Fatalf("error loading container: %v", err) } @@ -1732,7 +1914,12 @@ func TestMountPropagation(t *testing.T) { defer os.RemoveAll(rootDir) defer os.RemoveAll(bundleDir) - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("creating container: %v", err) } @@ -1750,21 +1937,21 @@ func TestMountPropagation(t *testing.T) { // Check that mount didn't propagate to private mount. privFile := filepath.Join(priv, "mnt", "file") - args := &control.ExecArgs{ + execArgs := &control.ExecArgs{ Filename: "/usr/bin/test", Argv: []string{"test", "!", "-f", privFile}, } - if ws, err := cont.executeSync(args); err != nil || ws != 0 { + if ws, err := cont.executeSync(execArgs); err != nil || ws != 0 { t.Fatalf("exec: test ! -f %q, ws: %v, err: %v", privFile, ws, err) } // Check that mount propagated to slave mount. slaveFile := filepath.Join(slave, "mnt", "file") - args = &control.ExecArgs{ + execArgs = &control.ExecArgs{ Filename: "/usr/bin/test", Argv: []string{"test", "-f", slaveFile}, } - if ws, err := cont.executeSync(args); err != nil || ws != 0 { + if ws, err := cont.executeSync(execArgs); err != nil || ws != 0 { t.Fatalf("exec: test -f %q, ws: %v, err: %v", privFile, ws, err) } } @@ -1813,7 +2000,12 @@ func TestMountSymlink(t *testing.T) { defer os.RemoveAll(rootDir) defer os.RemoveAll(bundleDir) - cont, err := Create(testutil.UniqueContainerID(), spec, conf, bundleDir, "", "", "") + args := Args{ + ID: testutil.UniqueContainerID(), + Spec: spec, + BundleDir: bundleDir, + } + cont, err := New(conf, args) if err != nil { t.Fatalf("creating container: %v", err) } @@ -1826,11 +2018,11 @@ func TestMountSymlink(t *testing.T) { // Check that symlink was resolved and mount was created where the symlink // is pointing to. file := path.Join(target, "file") - args := &control.ExecArgs{ + execArgs := &control.ExecArgs{ Filename: "/usr/bin/test", Argv: []string{"test", "-f", file}, } - if ws, err := cont.executeSync(args); err != nil || ws != 0 { + if ws, err := cont.executeSync(execArgs); err != nil || ws != 0 { t.Fatalf("exec: test -f %q, ws: %v, err: %v", file, ws, err) } } |